Clash가 자체 DNS를 갖춘 이유
Clash나 Clash Meta(mihomo)의 설정 파일을 열어보면 dns로 시작하는 항목이 통째로 들어 있습니다. 이건 장식이 아니고, 고급 사용자만 다루는 부분도 아닙니다.
시스템 프록시 모드에서는 브라우저가 도메인을 그대로 프록시에 넘겨 원격 서버가 해석하므로 로컬 DNS는 별 상관이 없어 보입니다. 하지만 프록시를 거치지 않고 통신사 DNS로 직접 UDP 53 쿼리를 보내는 앱이 하나라도 있으면 DNS 스푸핑과 정보 유출이 그대로 재현됩니다. 조작된 가짜 IP를 받을 수 있고, 조회 기록도 로컬 네트워크 측에 그대로 남습니다.
TUN 모드에서는 모든 트래픽이 가상 네트워크 어댑터로 들어가므로 도메인 해석이 먼저 이루어져야 합니다. Clash의 내장 DNS 모듈이 바로 이 역할을 담당합니다. 53번 포트로 들어오는 쿼리를 일괄 가로채어, 설정에 따라 어느 서버에 질의할지, 어떤 방식으로 질의할지, 어느 쪽 응답을 신뢰할지를 결정합니다.
결국 dns 항목을 제대로 설정했는지가 세 가지를 좌우합니다. 웹 페이지 로딩 속도, 조작된 주소를 받을 위험, 조회 기록이 누구 손에 남는지입니다.
dns 항목 필드 하나씩 살펴보기
스위치 3종: enable / listen / ipv6
enable: 전체 스위치입니다. false로 두면 이 항목 전체가 작동하지 않고 Clash가 어떤 해석도 가로채지 않으므로 나머지 필드는 의미가 없어집니다.listen: 내장 DNS 서버가 대기하는 주소로, 흔히0.0.0.0:53으로 씁니다. TUN 하이재킹의 종착지이자, 같은 네트워크의 다른 기기가 Clash를 DNS로 이용할 때의 진입점이 바로 이 포트입니다. 로컬에서만 사용하고 TUN 하이재킹을 쓴다면 기본값 그대로 두면 됩니다.ipv6: false로 설정하면 AAAA 조회 결과를 버립니다. 인터넷 회선에 IPv6이 없다면 꺼두는 편이 좋습니다. 앱이 v6 주소를 받아 존재하지 않거나 더 느린 경로로 접속하는 상황을 막아줍니다.
enhanced-mode와 fake-ip-filter
redir-host: 전통 방식으로, 모든 도메인을 실제로 해석합니다. 호환성이 가장 좋지만 DNS 왕복이 한 번 더 발생하는 대가가 있습니다.fake-ip: 프록시 규칙에 걸리는 도메인은 곧바로 198.18.0.x 대역의 가상 주소를 반환해 실제 해석 과정을 생략합니다. 연결이 더 빨리 맺어지고, 앱이 직접 DNS 쿼리를 보내다가 스푸핑당하는 단계도 피할 수 있습니다.fake-ip-filter: 예외 목록으로, 여기 등록된 도메인은 반드시 실제 IP를 받아야 합니다. 대표적으로 로컬 도메인*.lan, 시간 서버, STUN 서버, 일부 제조사의 로그인 도메인이 해당됩니다. 특정 앱이 fake-ip 상태에서 이상 동작을 보이면 가장 먼저 해당 도메인을 이 목록에 추가해 보세요.
default-nameserver: 부트스트랩 DNS
이 필드는 한 가지 역할만 합니다. 설정에 도메인 형태로 적힌 DNS 서버(예: dns.alidns.com)를 IP로 해석하는 것입니다. proxy-server-nameserver를 따로 지정하지 않았다면 프록시 노드 도메인 해석도 이 필드가 맡습니다.
여기에는 순수 IP 형태의 UDP DNS만 적어야 합니다. 예: 223.5.5.5, 119.29.29.29. DoH 주소를 적으면 「해석을 하려면 먼저 해석이 필요한」 순환 구조가 생겨 dns 항목 전체가 멈춰버립니다.
nameserver: 기본 해석 목록
기본으로 쓰이는 도메인 해석 서버로, 여러 대에 동시 질의해 가장 빠른 응답을 채택합니다. 표기법은 네 가지입니다. 순수 IP는 UDP 53, tls://로 시작하면 DoT, https://로 시작하면 DoH, system이라고 쓰면 시스템 DNS를 그대로 사용합니다.
국내(중국 본토) 환경이라면 현지 DoH만 적으면 됩니다. https://dns.alidns.com/dns-query, https://doh.pub/dns-query 같은 서비스는 지연이 낮고 로컬 CDN 라우팅 결과와도 잘 맞습니다.
fallback과 fallback-filter
fallback은 nameserver와 동시에 질의를 보내며, 「스푸핑됐을 가능성이 있거나 원래 프록시를 거쳐야 하는」 도메인을 처리합니다. 보통 해외의 신뢰할 수 있는 DNS를 적습니다. 예: https://dns.cloudflare.com/dns-query, tls://8.8.4.4:853.
fallback-filter는 어느 쪽 응답을 신뢰할지 결정하며, 하위 필드 네 개가 각자 역할을 맡습니다.
geoip와geoip-code: nameserver가 반환한 IP가 지정 지역(예: CN)에 속하지 않으면 스푸핑으로 판단해 fallback의 응답을 채택합니다.geosite: 도메인이 gfw 등 특정 분류에 해당하면 곧바로 fallback의 결과를 채택합니다.ipcidr: 반환된 IP가240.0.0.0/4처럼 예약된 대역에 속하면 스푸핑으로 판단합니다.domain: 목록에 등록된 도메인은 조건 없이 fallback을 사용합니다.
한 가지 덧붙이면, mihomo의 최신 버전에서는 nameserver-policy와 분기 라우팅 방식을 더 권장합니다. fallback은 여전히 호환되므로 기존 설정을 급하게 바꿀 필요는 없습니다.
nameserver-policy: 도메인별 지정 (고급)
도메인이나 분류별로 전용 해석 서버를 지정하며, nameserver와 fallback보다 우선순위가 높습니다. 대표적인 예로 'geosite:cn'은 국내 DoH를, '+.internal.example.com'은 사내망 DNS를 가리키게 설정합니다. fallback-filter보다 더 세밀한 분기가 가능해 해석 경로를 명확히 통제해야 하는 상황에 적합합니다.
「DNS 하이재킹」이 실제로 가로채는 것
설정에서 말하는 하이재킹이란 Clash가 로컬에서 발생하는 53번 포트 쿼리를 능동적으로 가로채 내장 DNS가 위 규칙에 따라 응답하도록 하는 것을 뜻하며, 다른 사람의 트래픽을 가로채는 것이 아닙니다.
TUN 모드에서 tun.enable과 dns-hijack을 설정하면 가상 네트워크 어댑터로 들어오는 모든 DNS 요청이 수집됩니다. 이는 가장 철저하게 커버하는 방식으로, 어떤 앱도 이를 우회할 수 없습니다.
시스템 프록시 모드는 DNS를 가로채지 않습니다. 브라우저가 도메인을 프록시 원격 서버에 넘겨 해석하는 데는 문제가 없지만, 로컬에서 직접 연결하는 앱은 여전히 시스템 DNS를 사용합니다. 이 틈을 막으려면 TUN을 켜거나, 시스템 DNS를 listen에 적은 주소로 직접 변경해야 합니다.
listen은 로컬 또는 사내망에서만 접근 가능하게 유지하고, 내장 DNS를 공용 인터넷에 노출하지 마세요. 개방형 재귀 DNS는 스캐너에 발견되어 증폭 공격에 악용될 수 있습니다.
바로 적용 가능한 설정 두 가지
방안 1: 가정용 일반 설정
fake-ip로 속도를 높이고, 국내 도메인은 알리바바와 텐센트의 DoH를 사용하며, gfw 분류에 걸리거나 CN이 아닌 결과가 나오는 도메인은 자동으로 fallback을 사용합니다. 대다수 가정용 인터넷 환경에 적합해 웹 페이지가 즉시 열리고 국내 CDN도 우회하지 않습니다.
dns:
enable: true
listen: 0.0.0.0:53
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "*.local"
- "*.msftconnecttest.com"
- "time.*.com"
- "localhost.ptlogin2.qq.com"
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
fallback:
- https://dns.cloudflare.com/dns-query
- tls://8.8.4.4:853
fallback-filter:
geoip: true
geoip-code: CN
geosite:
- gfw
ipcidr:
- 240.0.0.0/4
방안 2: 엄격한 유출 방지 설정
respect-rules: true를 설정하면 nameserver로 보내는 쿼리 자체가 규칙에 따라 프록시를 거치게 되어 조회 내용이 로컬 통신사 측에 남지 않습니다. direct-nameserver는 직결 도메인을, proxy-server-nameserver는 노드 도메인을 담당해 역할이 명확히 분리됩니다.
dns:
enable: true
listen: 0.0.0.0:53
ipv6: false
respect-rules: true
enhanced-mode: fake-ip
fake-ip-filter:
- "*.lan"
- "*.local"
default-nameserver:
- 223.5.5.5
- 119.29.29.29
proxy-server-nameserver:
- https://dns.alidns.com/dns-query
direct-nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
nameserver:
- https://dns.cloudflare.com/dns-query
- https://dns.google/dns-query
여기에 TUN을 더해 전체 53번 포트를 수집하면 우회 경로를 남기지 않습니다.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
대가도 짚어두어야 합니다. 해외 DoH가 프록시를 거치므로 첫 해석이 다소 느려지고, 프록시를 쓸 수 없을 때는 해석 자체가 전부 실패할 수 있습니다. 이런 결합 구조를 감안해야 합니다.
설정 변경 후, 3단계 검증
- 로그 확인: 클라이언트 로그의 [DNS] 줄에는 각 도메인이 어느 서버를 사용했고 어떤 정책에 걸렸는지 표시됩니다. 먼저 분기가 예상대로 동작하는지 확인하세요.
- 검사 페이지 열기: 브라우저로 DNS 유출 검사 사이트에 접속해보세요. 표시되는 출구 서버는 설정한 DoH 제공사나 프록시 출구여야 하며, 로컬 통신사가 아니어야 합니다.
- 명령줄로 확인:
nslookup example.com 127.0.0.1을 실행해 내장 DNS에 직접 질의합니다. fake-ip 모드에서 프록시 대상 도메인이 198.18.x.x를 반환하는 것은 정상이며 오류가 아닙니다.
YAML 들여쓰기 오류가 dns 항목이 작동하지 않는 가장 흔한 원인입니다. 필드 앞에 공백 두 칸을 통일해 사용하고, 수정 후에는 설정을 다시 로드하거나 코어를 재시작한 뒤 다시 테스트하세요.
자주 발생하는 문제 세 가지
- 국내(중국 본토) 사이트가 느리게 열리는 경우: fallback에 해외 DNS만 넣고 geosite 분기를 설정하지 않아 국내 도메인이 해외 서버에서 해석되면서 CDN 라우팅이 엇나간 상황입니다.
- 특정 앱의 네트워크 연결이 이상한 경우: 대부분 실제 IP가 필요한 경우이므로 해당 도메인을 fake-ip-filter에 추가하세요.
- 설정이 적용되지 않는 것처럼 보이는 경우:
enable: true여부와 들여쓰기가 올바른지 확인하고, 사용 중인 클라이언트가 GUI에서 dns 항목을 덮어쓰고 있지 않은지도 확인하세요.