Clash DNS는 실제로 무엇을 처리할까
웹사이트에 접속할 때 애플리케이션은 보통 먼저 시스템 DNS에 도메인 조회를 요청한 다음, 반환된 IP로 연결을 설정합니다. 시스템이 미리 조회를 완료하면 Clash에는 대상 IP만 전달될 수 있어 도메인 규칙, GeoSite 규칙, 스니핑으로 복원해야 하는 도메인 정보가 제대로 활용되지 않을 수 있습니다. Clash 내장 DNS를 활성화하면 동일한 프록시 코어가 조회 요청을 처리하므로 도메인, 규칙 매칭, 아웃바운드 선택의 관계가 더 명확해집니다.
DNS 설정은 공용 서버 하나를 입력하는 작업으로 끝나지 않습니다. 한 번의 조회에는 부트스트랩 리졸버, 일반 리졸버, 프록시 노드 도메인 리졸버, 보조 리졸버, 도메인 정책, TUN 하이재킹이 관여할 수 있습니다. 각 필드는 서로 다른 단계를 담당하므로 중복 입력이 안정성을 자동으로 높여 주지는 않으며, 오히려 조회 루프나 결과 불일치를 일으킬 수 있습니다.
한 번의 DNS 조회가 진행되는 주요 경로
- 브라우저나 애플리케이션이
www.example.com같은 도메인의 조회를 요청합니다. - 시스템 DNS, TUN 하이재킹 또는 수동으로 지정한 로컬 포트가 조회를 Clash에 전달합니다.
- 코어는 먼저 캐시, hosts, fake-ip-filter 및 nameserver-policy를 확인합니다.
- 특정 정책과 일치하지 않으면 조회가 nameserver로 전달되며, fallback이 활성화된 경우 fallback-filter를 함께 적용해 결과를 판단합니다.
- 코어가 실제 IP를 반환하거나 Fake-IP 모드에서는
198.18.0.0/16범위의 매핑 주소를 반환합니다. - 애플리케이션이 연결을 시작하면 Clash가 도메인 규칙, IP 규칙 및 프록시 그룹에 따라 아웃바운드를 결정합니다.
nameserver, default-nameserver 및 proxy-server-nameserver
nameserver: 일반 도메인 조회 진입점
dns.nameserver는 기본 리졸버 목록입니다. nameserver-policy와 일치하지 않고 fallback이 개입할 필요도 없을 때 일반 도메인은 이 서버로 전달됩니다. 기존 UDP DNS는 물론 DoH, DoT 같은 암호화 프로토콜도 사용할 수 있습니다. UDP DNS는 보통 IP 주소로 작성하며 기본 포트는 53입니다. DoH는 완전한 HTTPS 주소를 사용하고, DoT는 일반적으로 tls://호스트명:853 형식을 사용합니다.
dns:
enable: true
listen: 127.0.0.1:1053
nameserver:
- 223.5.5.5
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
하나의 목록에 여러 서버를 넣을 수 있지만, '여러 개'라고 해서 엄격한 순서의 장애 조치가 되는 것은 아닙니다. 코어 버전에 따라 동시에 조회한 뒤 먼저 도착했거나 조건에 맞는 결과를 사용할 수 있습니다. 한국 국내 도메인과 그 외 도메인을 항상 다른 리졸버로 처리하려면 목록 순서에 의존하지 말고 nameserver-policy를 사용하세요.
default-nameserver: DNS 서버 자체의 호스트명 조회
nameserver에 https://dns.alidns.com/dns-query를 입력하면 코어가 HTTPS 연결을 만들기 전에 dns.alidns.com의 IP를 알아야 합니다. default-nameserver는 이 부트스트랩 단계에서 사용되며 bootstrap DNS라고도 합니다. 여기에는 직접 접근할 수 있는 IP 형식의 리졸버를 우선 지정해 '리졸버 호스트명을 먼저 조회해야 하는' 순환 의존을 피하세요.
dns:
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
default-nameserver가 모든 웹사이트의 필수 조회 경로인 것은 아닙니다. 정상적으로 시작된 뒤에는 일반 도메인을 nameserver, fallback 또는 nameserver-policy가 처리합니다. 이 단계의 조회 횟수는 보통 적지만 네트워크 전환, 캐시 만료, 리졸버 연결 재수립 시 다시 사용될 수 있습니다.
proxy-server-nameserver: 노드 도메인 전용 조회기
프록시 노드 주소는 고정 IP가 아니라 node.example.net 같은 도메인일 수 있습니다. 노드 도메인 조회마저 아직 연결되지 않은 프록시에 의존하면 순환이 발생합니다. 프록시에 연결하려면 노드 조회가 필요하고, 노드 조회에는 먼저 프록시 연결이 필요해지는 구조입니다. mihomo의 proxy-server-nameserver는 노드 서버 도메인을 직접 연결 가능한 DNS로 전달합니다.
dns:
proxy-server-nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
노드 도메인 조회에 실패하면 로그에 lookup, no such host, i/o timeout 등이 자주 표시됩니다. 이때 일반 웹 도메인이 정상적으로 조회되더라도 프록시 노드는 모두 타임아웃이 될 수 있습니다. 문제를 확인할 때는 nameserver와 proxy-server-nameserver를 따로 점검해야 하며, 브라우저에서 웹페이지가 열리는지만으로 판단해서는 안 됩니다.
fallback과 fallback-filter 설정 방법
fallback은 보조 리졸버 그룹으로, 서로 다른 네트워크 경로에서 얻은 DNS 결과를 선별할 때 주로 사용합니다. 'nameserver가 타임아웃된 뒤에만 조회하는' 단순한 대체 목록은 아닙니다. 기존 Clash 설정은 nameserver와 fallback에 병렬로 조회한 다음 fallback-filter로 보조 결과의 채택 여부를 판단하는 경우가 많습니다. mihomo도 호환 설정을 지원하지만, 더 정확한 도메인 분기는 보통 nameserver-policy로 구성하는 편이 적합합니다.
fallback-filter의 네 가지 조건
geoip: IP 지리 데이터베이스를 기반으로 결과를 판단합니다.geoip-code: 기준 지역 코드를 지정합니다(예:CN). 이 로직은 로컬 GeoIP 데이터가 최신 상태인지에 따라 달라집니다.ipcidr: 기본 조회 결과가 지정된 네트워크 대역에 들어오면 필터 규칙에 따라 fallback 결과를 선택합니다. 명백히 비정상적인 주소 대역을 제외할 때 주로 사용합니다.domain: 지정한 도메인은 fallback 측 결과를 직접 사용하며 도메인 접미사 형식을 지원합니다.
dns:
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
fallback:
- https://1.1.1.1/dns-query
- https://dns.google/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
domain:
- +.google.com
- +.githubusercontent.com
이 설정은 로컬 조회 결과와 다른 경로의 조회 결과를 구분해야 하는 네트워크 환경에 더 적합합니다. 모든 지역에 적합한 것은 아닙니다. 중국 본토 네트워크가 아닌 곳에서 geoip-code를 CN으로 고정하면 필터 기준이 실제 접속 위치와 어긋날 수 있습니다. 여러 지역을 이동하며 사용하는 기기라면 도메인별로 리졸버를 명시하는 편이 유지 관리하기 쉽습니다.
nameserver-policy로 도메인별 리졸버 지정하기
mihomo의 nameserver-policy는 도메인 매칭 결과에 따라 DNS를 지정할 수 있습니다. '기본 리졸버와 지역 필터' 방식보다 직접적입니다. 규칙과 일치한 도메인은 지정된 서버로 전달되고, 일치하지 않는 도메인은 nameserver로 돌아갑니다. 전체 도메인, 도메인 접미사를 입력할 수 있으며 GeoSite 데이터를 지원하는 코어에서는 geosite: 매칭도 사용할 수 있습니다.
dns:
enable: true
nameserver:
- https://1.1.1.1/dns-query
- https://dns.google/dns-query
nameserver-policy:
"geosite:cn":
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
"+.example.cn":
- https://dns.alidns.com/dns-query
"intranet.example.net":
- 192.168.1.1
마지막 예시는 내부망 환경을 보여 줍니다. 회사나 가정의 내부 도메인을 LAN DNS로만 조회할 수 있다면 해당 도메인에 192.168.1.1을 별도로 지정해야 하며, 모든 도메인이 공유하는 nameserver에 LAN DNS를 넣어서는 안 됩니다. 이렇게 하면 내부 서비스 조회는 유지하면서 모든 공용 도메인이 라우터를 거치지 않도록 할 수 있습니다.
설정에서 geosite:cn을 사용한다면 GeoSite 데이터가 존재하고 코어와 호환되는 형식인지 확인해야 합니다. 시작 로그에 규칙 세트 로드 실패, 데이터베이스 누락 또는 matcher 오류가 나타나면 먼저 코어 데이터 파일을 업데이트하세요. 외부 데이터 의존성을 줄이려면 +.example.com 같은 도메인 접미사 규칙만 사용할 수도 있습니다.
도메인 정책과 프록시 규칙은 서로 다릅니다
nameserver-policy는 '어느 DNS에 조회할지'를 결정하고, 프록시 규칙은 '어느 아웃바운드로 연결할지'를 결정합니다. 특정 도메인을 로컬 DoH로 조회한다고 해서 연결이 반드시 DIRECT가 되는 것은 아니며, 원격 DNS로 결과를 받는다고 해서 반드시 프록시를 사용하는 것도 아닙니다. 두 규칙을 따로 확인해 DNS 선택을 프록시 그룹 선택으로 착각하지 않도록 하세요.
Fake-IP, redir-host 및 필터 목록
enhanced-mode의 대표적인 값은 fake-ip와 redir-host입니다. Fake-IP 모드는 애플리케이션에 실제 주소를 즉시 반환하지 않고 매핑 주소를 먼저 반환합니다. 애플리케이션이 해당 주소로 연결하면 Clash가 연결을 원래 도메인으로 정확히 복원한 뒤 도메인 규칙을 적용할 수 있습니다. 기본 매핑 대역은 보통 198.18.0.1/16을 사용하며, 이 대역은 벤치마크용으로 예약되어 일반 공용 IP가 아닙니다.
dns:
enable: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "+.local"
- "localhost"
- "time.*.com"
- "ntp.*.com"
LAN 기기 검색, 프린터, 화면 미러링, NTP 시간 동기화 및 실제 IP에 의존하는 일부 애플리케이션은 Fake-IP와 맞지 않을 수 있습니다. 해당 도메인을 fake-ip-filter에 추가하면 실제 조회 결과가 반환됩니다. 모든 일반 최상위 도메인으로 필터 범위를 넓히면 Fake-IP의 도메인 식별 및 분기 효과가 크게 떨어지므로 피해야 합니다.
redir-host는 실제 IP를 애플리케이션에 직접 반환하므로 호환 경로가 직관적이지만, 연결이 코어에 들어온 뒤 IP 정보만 남을 수 있습니다. 이때 도메인 규칙 적용 여부는 연결 메타데이터, DNS 매핑 캐시 및 도메인 스니핑에 따라 달라집니다. TUN을 사용하는 데스크톱 환경에서 도메인 규칙 비중이 높다면 먼저 Fake-IP를 테스트하세요. LAN 서비스에 문제가 많을 때는 모드를 바로 끄기보다 필터를 항목별로 추가하는 편이 좋습니다.
TUN 모드에서의 DNS 하이재킹
dns.enable만 활성화한다고 해서 모든 프로그램이 Clash DNS를 사용하는 것은 아닙니다. 브라우저가 자체 보안 DNS를 사용할 수 있고 시스템이 여전히 UDP 53 조회를 라우터로 보낼 수도 있으며, 일부 애플리케이션은 시스템 프록시를 우회합니다. TUN 모드의 dns-hijack은 지정된 포트의 DNS 트래픽을 가로채 코어에서 처리하도록 합니다.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
any:53은 일반 UDP 53 조회를 가로채고, tcp://any:53은 TCP 53 조회를 가로챕니다. 하지만 DoH는 HTTPS에서 동작하며 보통 443 포트를 사용하므로 애플리케이션이 직접 보내는 DoH 요청까지 자동으로 가로채지는 않습니다. 브라우저가 자체 DoH를 지정하면 조회 요청이 Clash DNS로 들어오지 않을 수 있습니다. 문제를 확인할 때는 브라우저 보안 DNS를 잠시 '시스템 설정 사용'으로 바꾼 뒤 로그를 비교하세요.
TUN을 활성화한 뒤에도 시스템 권한이 필요합니다. Windows에서는 보통 코어가 가상 네트워크 어댑터와 라우팅을 생성해야 하고, macOS에서는 네트워크 확장 또는 VPN 설정 권한을 요청하며, Linux에서는 TUN 장치에 접근하고 라우팅을 수정해야 합니다. 로그에 permission denied, 인터페이스 생성 실패 또는 라우트 추가 실패가 표시되면 먼저 권한을 해결하고 nameserver를 반복해서 수정하지 마세요.
listen 포트 선택 방법
listen: 127.0.0.1:1053은 로컬 테스트에 적합하며 LAN의 다른 기기에 직접 공개되지 않습니다. 다른 기기가 이 컴퓨터를 DNS로 사용해야 한다면 LAN 인터페이스에서 수신하도록 설정하고 시스템 방화벽과 고정 주소도 구성해야 합니다. 포트 53은 시스템 리졸버, 가상 머신 소프트웨어 또는 다른 DNS 프로그램이 사용할 수 있으므로 1053, 5353 같은 고번 포트가 문제 해결에 더 적합합니다. 다만 5353은 mDNS 서비스와 충돌할 수도 있습니다.
mihomo 권장 설정 예시
다음은 데스크톱에서 시작하기에 적합한 mihomo 설정입니다. Fake-IP, 두 개의 DoH 리졸버, 별도의 노드 도메인 리졸버 및 TUN DNS 하이재킹을 사용합니다. DNS 주소는 현재 네트워크에서 실제로 접근 가능한지에 따라 조정해야 하며, '완전한 설정'을 위해 안정적으로 연결되지 않는 주소를 남겨 둘 필요는 없습니다.
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
proxy-server-nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
nameserver-policy:
"+.local":
- 192.168.1.1
"+.lan":
- 192.168.1.1
fake-ip-filter:
- "*.lan"
- "+.local"
- "localhost"
- "time.*.com"
- "ntp.*.com"
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
이 예시는 ipv6을 false로 설정했으며, 로컬 IPv6 라우팅이 불안정하거나 프록시 노드가 IPv6을 지원하지 않을 때 적합합니다. 광대역, LAN 및 노드가 모두 IPv6을 제대로 처리한다면 true로 바꾸고 규칙에 IPv6 주소 대역이 포함되어 있는지도 확인하세요. DNS의 IPv6 응답만 켜고 사용 가능한 IPv6 아웃바운드가 없으면 애플리케이션이 AAAA 주소를 먼저 시도하다가 타임아웃되는 경우가 많습니다.
가져오기 전에 현재 정상적으로 사용하는 설정을 복사해 두세요. 일반적인 데스크톱 클라이언트에서는 '프로필'에서 현재 구독 또는 로컬 설정의 편집 화면으로 이동할 수 있습니다. 구독 설정은 업데이트할 때 수동 수정 사항을 덮어쓸 수 있으므로 클라이언트에서 제공하는 오버라이드, 확장 설정 또는 Mixin 기능을 사용하는 편이 안전합니다. 저장한 뒤 코어 시작 로그에서 YAML 들여쓰기 오류, 알 수 없는 필드 또는 포트 충돌이 없는지 확인하세요.
DNS가 예상대로 작동하는지 확인하기
1단계: 코어 로그 확인
설정을 저장하고 코어를 재시작한 뒤 먼저 30초 동안 로그를 관찰하세요. DNS, lookup, timeout, connection refused, address already in use, failed to parse를 중점적으로 검색해야 합니다. 127.0.0.1:1053이 이미 사용 중이라면 해당 프로그램을 종료하거나 listen 포트를 사용 가능한 값으로 바꾸세요.
2단계: 로컬 수신 포트에 직접 조회
dig가 설치된 시스템에서는 브라우저 캐시를 우회해 Clash DNS를 직접 테스트할 수 있습니다. 다음 명령은 로컬 주소와 1053 포트를 명시합니다:
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA
Fake-IP 모드에서 A 레코드가 198.18.0.0/16 범위의 주소를 반환하는 것은 정상입니다. fake-ip-filter에 추가한 도메인은 실제 주소를 반환해야 합니다. 두 종류의 도메인이 완전히 같은 결과를 보인다면 enhanced-mode가 적용되었는지, 구독 업데이트가 설정을 덮어썼는지, 현재 실행 중인 설정이 방금 편집한 파일인지 확인하세요.
3단계: 규칙 및 연결 로그 비교
테스트용 도메인을 열고 연결 기록에 대상 IP만이 아니라 도메인이 표시되는지 확인하세요. 이어서 적용된 규칙과 프록시 그룹을 점검합니다. DNS 조회는 성공했지만 연결에 실패한다면 문제는 대개 노드, 라우팅 또는 규칙 단계에 있습니다. DNS 로그 자체가 타임아웃된다면 리졸버 접근성, 프록시 노드 도메인 및 방화벽을 계속 확인해야 합니다.
4단계: 네트워크 전환 테스트
가정용 인터넷, 휴대폰 핫스팟 또는 다른 네트워크에서 각각 테스트하세요. 전환할 때마다 인터페이스, 라우팅 및 DNS 캐시가 갱신되도록 10~30초 기다립니다. 특정 네트워크에서만 실패한다면 해당 네트워크가 특정 DNS 프로토콜을 차단하거나 IPv6 라우팅에 문제가 있거나 DoH 서버에 접근하지 못하는 경우가 많습니다. 이때 모든 파라미터를 한꺼번에 바꾸기보다 UDP DNS 하나와 DoH 하나를 잠시 유지해 비교하세요.
자주 발생하는 오류와 처리 순서
오류 1: 노드는 모두 타임아웃되지만 웹 도메인은 조회됨
먼저 proxy-server-nameserver를 확인하세요. 노드 주소가 도메인이라면 일반 nameserver가 정상이어도 노드 도메인이 사용 가능한 경로로 조회된다는 보장은 없습니다. 또한 nameserver-policy가 노드 도메인을 프록시 연결 후에만 접근할 수 있는 DNS로 보내고 있지 않은지도 확인해야 합니다.
오류 2: TUN을 켠 뒤 LAN 기기에 접속할 수 없음
라우터, NAS, 프린터 및 화면 미러링 서비스가 사용하는 도메인을 fake-ip-filter에 추가하고 내부 도메인에는 nameserver-policy를 설정하세요. LAN에서 흔히 쓰는 접미사는 .lan과 .local이지만 실제 이름은 라우터 DHCP 또는 내부 DNS 설정을 기준으로 해야 합니다. DHCP 임대 갱신 후 IP가 바뀔 수 있으므로 현재 기기 IP만 추가하지 마세요.
오류 3: 브라우저에서는 열리지만 명령줄 프로그램은 실패함
브라우저는 자체 DoH를 사용하고 명령줄 프로그램은 시스템 DNS에 의존할 수 있습니다. 또는 브라우저는 시스템 프록시를 사용하지만 명령줄 프로그램은 TUN만 사용할 수도 있습니다. 먼저 브라우저의 독립 보안 DNS를 끄고 비교한 다음 dig로 Clash 수신 포트를 조회하세요. 로컬 조회가 정상이면 시스템 프록시, TUN 라우팅 및 해당 명령줄 프로그램이 리졸버를 고정 지정했는지 확인하세요.
오류 4: 규칙이 가끔 도메인이 아닌 IP와 매칭됨
DNS 조회가 실제로 Clash를 통과하는지 확인하고 enhanced-mode를 점검하세요. redir-host를 사용한다면 코어가 지원하는 도메인 스니핑을 활성화할 수 있지만 모든 프로토콜에서 도메인을 복원할 수 있는 것은 아닙니다. 도메인 규칙 의존도가 높은 데스크톱 환경에서는 적절한 필터 목록과 Fake-IP를 함께 사용하는 편이 일반적으로 안정적입니다.
오류 5: 설정 업데이트 후 수동 수정 사항이 사라짐
구독 업데이트는 보통 설정 파일을 다시 작성합니다. DNS 사용자 설정은 클라이언트의 오버라이드, 확장 스크립트 또는 Mixin에 넣거나 별도의 로컬 설정으로 관리해야 합니다. 편집하기 전에 '설정' → '코어'에 표시된 실제 코어를 기록하고, '로그'에서 로드된 파일 경로를 확인해 현재 설정에 사용되지 않는 사본을 수정하지 않도록 하세요.
설정 선택 기준 요약
- 일반 도메인 조회는 nameserver에, DoH 시작에 필요한 부트스트랩 조회는 default-nameserver에 지정합니다.
- 프록시 노드가 도메인을 사용할 때는 직접 접근 가능한 proxy-server-nameserver를 설정해 순환 의존을 피합니다.
- 도메인별 고정 분기에는 nameserver-policy를 우선 사용하고, fallback-filter는 기존의 이중 리졸버 선별 방식과의 호환이 필요할 때 적합합니다.
- TUN 환경에서는 dns-hijack으로 UDP 53 및 TCP 53을 가로챌 수 있지만 애플리케이션이 자체적으로 보내는 DoH까지 자동으로 처리하지는 않습니다.
- Fake-IP는 도메인 정보를 유지하는 데 도움이 됩니다. LAN, 시간 동기화 또는 기기 검색에 문제가 생기면 fake-ip-filter를 항목별로 추가하세요.
- 한 번에 한 그룹의 파라미터만 수정하고 코어를 재시작한 뒤 로그와 로컬 포트 조회로 검증하세요. DNS, 규칙 및 노드를 동시에 바꾸지 않는 것이 좋습니다.
유지 관리하기 쉬운 Clash DNS 설정에는 많은 서버를 쌓을 필요가 없습니다. 먼저 일반 도메인, 노드 도메인, 내부 도메인을 각각 어떤 리졸버가 처리할지 정한 다음 fallback, Fake-IP 및 TUN 하이재킹이 필요한지 결정하세요. 경로가 명확하면 조회 실패, 잘못된 규칙 매칭, LAN 충돌을 해당 필드부터 추적할 수 있습니다.