Clash DNS 설정 필드 총정리: nameserver, fallback, DNS 가로채기
nameserver, fallback, fallback-filter, dns-hijack의 역할과 fake-ip·redir-host 차이를 살펴보고, DNS 오류를 점검하는 순서를 안내합니다.
DNS 조회, 요청 가로채기, 프록시 라우팅을 구분하기
Clash DNS 설정에서는 세 가지를 따로 살펴봐야 합니다. 도메인을 어디서 조회하는지, 앱의 DNS 요청을 어떻게 코어로 전달하는지, 연결이 최종적으로 어떤 경로를 이용하는지입니다. nameserver는 업스트림 리졸버를 지정하고, tun.dns-hijack은 조건에 맞는 DNS 트래픽을 가로채며, rules는 실제 연결의 경로를 결정합니다. 서로 연관은 있지만 각각의 역할을 대신할 수는 없습니다.
이 글은 현재 mihomo 코어를 사용하는 클라이언트를 기준으로 설명합니다. 구버전 Clash나 다른 포크, 클라이언트의 설정 생성기에서는 지원하는 필드가 다를 수 있습니다. 또한 UI의 ‘DNS 덮어쓰기’ 기능이 구독 설정의 dns 섹션 전체를 대체할 수도 있습니다. 문제를 진단할 때는 구독 편집 화면뿐 아니라 클라이언트가 실제로 생성해 코어에 전달한 설정을 확인하세요.
- 코어 DNS:
dns.enable을 활성화해야 코어가 해당 섹션의 설정에 따라 DNS 조회를 처리합니다. - 시스템 DNS: 운영체제가 현재 사용하는 DNS 경로입니다. HTTP 시스템 프록시만 켜도 모든 DNS 요청이 코어를 거치는 것은 아닙니다.
- 프록시 규칙: 도메인이나 IP에 적용되는 규칙에 따라 직접 연결할지 프록시를 사용할지가 결정됩니다. 특정 지역의 DNS를 사용한다고 해서 해당 지역의 프록시 노드가 선택되는 것은 아닙니다.
- 앱 자체 DNS: 브라우저의 보안 DNS나 앱에 내장된 DoH는 시스템의 기존 DNS 설정을 우회할 수 있습니다.
여기서 ‘DNS 가로채기’란 지정한 DNS 트래픽을 로컬 코어로 리디렉션하는 것을 뜻합니다. 통신사가 조회 결과를 조작한다는 의미는 아닙니다. 실제로 요청이 가로채졌는지는 조회 결과와 연결 로그로 확인해야 합니다.
nameserver와 default-nameserver: 일반 조회와 부트스트랩 조회
먼저 별도로 테스트할 수 있는 DNS 리스너 만들기
아래는 기존 mihomo 설정에 병합해 사용할 DNS 예시이며, 노드와 규칙까지 포함한 전체 설정 파일은 아닙니다. 리스닝 주소는 로컬로 제한하고 포트는 1053을 사용해 시스템의 53 포트와 직접 충돌하지 않도록 했습니다. 이 상태에서는 시스템이 자동으로 이 리스너를 사용하지 않으므로, 뒤에서 지정한 주소로 직접 조회해 테스트합니다.
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
nameserver는 일반 도메인 조회에 사용할 업스트림 목록입니다. 기존 DNS 주소, DoH(DNS over HTTPS) 또는 코어가 지원하는 다른 프로토콜을 지정할 수 있습니다. 주소를 두 개 나열한다고 해서 첫 번째는 주 서버, 두 번째는 장애 시 대체 서버라는 뜻은 아닙니다. 장애 전환을 위해 목록 순서에 의존하지 마세요.
default-nameserver는 주로 DNS 업스트림의 도메인 이름을 조회할 때 사용합니다. 예를 들어 https://dns.alidns.com/dns-query에 연결하려면 먼저 dns.alidns.com의 IP 주소를 알아야 합니다. IP 주소로 부트스트랩 리졸버를 지정하면 ‘DNS 서버의 도메인을 조회하는 데 해당 서버가 필요하다’는 순환 의존을 피할 수 있습니다.
노드 도메인 조회와 DNS 아웃바운드는 따로 확인하기
mihomo의 proxy-server-nameserver는 프록시 노드 서버의 도메인을 전용으로 조회할 수 있습니다. 노드 주소 자체를 조회하지 못하면 서비스 도메인의 DNS가 정상이어도 프록시 연결을 만들 수 없습니다. respect-rules를 켜 DNS 업스트림 연결에 라우팅 규칙을 적용할 때는 노드 도메인 조회 경로도 올바르게 설정해야 합니다. 리졸버가 프록시에 의존하고 프록시가 다시 같은 리졸버에 의존하는 상황을 피하세요.
문제를 진단할 때 고급 필드를 한꺼번에 추가하지 마세요. 먼저 선택한 DoH 서버에 현재 네트워크에서 연결할 수 있는지 확인한 다음, 규칙에 따른 아웃바운드 설정 등을 추가하세요. DoH는 보통 TCP 443을 사용하지만, HTTPS라고 해서 자동으로 프록시를 통과하는 것은 아닙니다. 실제 경로는 코어 설정과 라우팅 조건에 따라 달라집니다.
fallback과 fallback-filter: 시간 초과용 백업이 아닌 결과 필터
fallback은 주 DNS가 시간 초과될 때만 사용하는 백업 목록으로 오해하기 쉽습니다. 실제로 코어는 nameserver와 fallback을 함께 조회하고 fallback-filter에 따라 어느 쪽 결과를 사용할지 판단합니다. 이는 프록시 노드의 대체 그룹이 아니며, 특정 도메인이 프록시를 사용하도록 보장하지도 않습니다.
아래 예시는 조건을 명시해 필터링하는 방법입니다. 앞서 나온 dns 섹션에 병합해야 하며, 같은 이름의 최상위 섹션을 파일에 하나 더 만들면 안 됩니다. 예시에서는 GeoIP 필터를 끄고 문서용 IP 대역과 특정 도메인으로 판단 방식을 설명합니다. 이 대역이 모든 비정상 주소를 망라하는 것은 아닙니다.
fallback:
- https://cloudflare-dns.com/dns-query
fallback-filter:
geoip: false
ipcidr:
- 0.0.0.0/8
- 192.0.2.0/24
- 198.51.100.0/24
- 203.0.113.0/24
domain:
- '+.github.com'
| 필드 | 판단 대상 | 설정 의미 |
|---|---|---|
geoip | 일반 조회 결과에 포함된 IP의 위치 정보 | GeoIP 조건을 활성화하며, 사용 가능한 위치 정보 데이터가 필요합니다. |
geoip-code | GeoIP 국가 또는 지역 코드 | GeoIP를 활성화하면 일반 조회 결과가 지정한 지역 조건에 맞지 않을 때 fallback 결과를 사용합니다. |
ipcidr | 일반 DNS 조회에서 반환된 IP | 지정된 IP 대역에 해당하면 fallback 결과를 사용합니다. |
domain | 조회한 도메인 | 일치하는 도메인은 fallback 측의 조회 결과를 사용합니다. |
geoip: true와 geoip-code: CN을 사용한다고 해서 ‘중국 본토 사이트는 직접 연결’된다는 뜻은 아닙니다. 조회된 IP의 위치 정보를 기준으로 결과를 사용할지 판단합니다. CDN 주소, 위치 정보 데이터의 업데이트 시점, 네트워크 출구에 따라 판단이 달라질 수 있으며, 프록시 출구는 여전히 규칙으로 결정됩니다. 특정 도메인에 고정된 리졸버를 지정하려면 지리적 필터를 여러 개 쌓기보다 nameserver-policy를 사용하는 편이 직관적입니다.
fallback 업스트림에도 연결할 수 있어야 합니다. 현재 네트워크에서 선택한 업스트림의 응답이 시간 초과된다면, 일부 도메인에 fallback 사용을 강제해도 장애 범위만 커집니다. 필터를 켜기 전에 업스트림 연결부터 별도로 확인하세요.
fake-ip와 redir-host: 가상 주소와 실제 주소의 차이
fake-ip는 주소 매핑으로 도메인 정보를 보존
fake-ip 모드에서는 코어가 앱에 198.18.0.0/16 범위의 가상 IPv4 주소를 반환하고, 도메인과 가상 주소의 매핑을 저장할 수 있습니다. 이후 앱이 해당 주소로 연결하면 트래픽이 같은 코어를 다시 거쳐야 코어가 도메인을 복원하고 규칙을 적용해 실제 연결을 수립합니다. 이 대역은 네트워크 테스트용으로 예약된 주소 공간이며, 웹사이트의 공인 IP 주소가 아닙니다.
따라서 조회 결과가 198.18.x.x라고 해서 DNS가 오염된 것은 아닙니다. 실제로 점검할 문제는 DNS 요청은 코어로 전달됐지만 연결이 일반 라우팅 경로로 나가는 경우, 또는 클라이언트를 바꾸거나 매핑을 지운 뒤에도 시스템에 이전 가상 주소가 캐시된 경우입니다. DNS만 가로채고 후속 연결은 처리하지 않는 것이 fake-ip 모드에서 접속되지 않는 흔한 원인입니다.
redir-host는 실제 IP를 반환하지만 연결도 올바르게 가로채야 함
redir-host 모드에서는 보통 업스트림에서 조회한 실제 IP를 반환하므로 앱이 가상 주소에 연결할 필요가 없습니다. 실제 주소에 의존하는 일부 프로그램과 호환하기 쉽지만, 캐시나 여러 도메인이 공유하는 IP 등의 영향으로 도메인과 연결의 연관성이 달라질 수 있습니다. 모드 이름에 REDIRECT가 들어간다고 해서 Linux의 REDIRECT 방화벽 규칙을 반드시 켜야 하는 것은 아니며, 투명 프록시가 자동으로 설정된다는 뜻도 아닙니다.
- TUN을 사용하면서 도메인 규칙 매칭 정보를 유지하려면 먼저
fake-ip를 테스트해 보세요. - 로컬 네트워크 검색, 특정 기기 또는 게임에서 호환성 문제가 생기면 먼저 해당 도메인을 확인한 다음
fake-ip-filter적용을 검토하세요. - 기본 blacklist 필터 모드에서는
fake-ip-filter에 추가한 도메인에 가상 주소를 반환하지 않습니다. 다른 필터 모드의 동작은 현재 mihomo 설정을 기준으로 확인하세요. - 모드를 변경한 뒤에는 영향을 받는 앱을 다시 시작하고 DNS 캐시를 비워 이전 모드의 결과가 섞이지 않도록 하세요.
dns.ipv6: false는 코어 DNS에서 AAAA 조회를 처리하는 방식을 제어하며, 시스템의 모든 IPv6 연결을 끄는 설정은 아닙니다. 브라우저가 자체 DoH를 사용하거나 앱에 IPv6 주소가 캐시되어 있으면 다른 경로로 연결될 수 있습니다.
tun.dns-hijack: 53 포트 가로채기의 범위
dns-hijack은 dns가 아닌 tun 섹션에 작성합니다. 아래는 mihomo에서 흔히 사용하는 TUN 설정 예시입니다. 이 설정은 라우팅을 변경하므로 원격 서버에서 작업하기 전에 콘솔 등 복구 방법을 준비하세요. 데스크톱 클라이언트는 보통 서비스 모드나 권한 부여 도우미를 통해 TUN 권한을 관리합니다. 권한을 어디서 얻는지 모르는 상태에서 코어를 중복 실행하지 마세요.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
any:53은 TUN으로 들어오는 UDP 53 DNS 트래픽을 대상으로 하고, tcp://any:53은 TCP 53을 추가로 처리합니다. 네트워크 전체를 검색하거나 차단하는 기능은 아닙니다. 먼저 트래픽이 TUN을 통과해야 코어가 처리할 수 있습니다. 라우팅 제외 설정, 운영체제 동작, 로컬 루프백 DNS 서비스 때문에 일부 요청은 이 경로를 거치지 않을 수 있습니다.
- DoH: 보통 HTTPS의
443포트를 사용하므로any:53을 설정해도 코어 DNS 조회로 바뀌지 않습니다. - DoT: 보통 TLS의
853포트를 사용하므로 기존 53 포트 가로채기 범위에 포함되지 않습니다. - Ubuntu 로컬 DNS:
127.0.0.53은 systemd-resolved의 로컬 스텁 주소인 경우가 많습니다. 이 주소가 보인다고 해서 DNS 가로채기가 실패했다고 단정할 수는 없습니다. - 로컬 네트워크 기기: 이 기기에서 TUN을 켜도 라우터나 다른 기기의 DNS까지 자동으로 가로채지는 않습니다. 게이트웨이에 배포하려면 별도의 포워딩 및 방화벽 설계가 필요합니다.
이 기기의 DNS 문제를 해결하려고 리스닝 주소를 0.0.0.0:53으로 바꾸고 공용 인터넷에 노출하지 마세요. 로컬 네트워크에 서비스를 제공해야 한다면 허용할 네트워크 대역을 제한하고 UDP와 TCP 방화벽 규칙을 각각 확인하세요.
Ubuntu 문제 해결 순서: 리스닝, 조회, 가로채기, 연결 경로
1단계: 실제 설정과 리스닝 프로세스 확인
명령줄로 설치한 경우 실제 설정 디렉터리를 대상으로 테스트할 수 있습니다. 아래 예시는 /etc/mihomo/config.yaml 경로를 사용합니다. 데스크톱 클라이언트에서는 클라이언트가 제공하는 실행 설정을 확인하고, 이 경로를 실제 설정 디렉터리 대신 사용하지 마세요.
mihomo -t -d /etc/mihomo -f /etc/mihomo/config.yaml
sudo ss -lntup 'sport = :1053'
resolvectl status
설정 테스트로 문법 및 설정 오류를 찾을 수 있지만 업스트림 네트워크에 연결할 수 있는지까지 확인되는 것은 아닙니다. ss로 올바른 프로세스가 1053 포트를 리스닝하는지 확인하세요. 주소가 이미 사용 중이면 다른 DNS 서비스를 먼저 찾아보고, 시스템 DNS 서비스를 무작정 중지하지 마세요.
2단계: 시스템 리졸버를 거치지 않고 코어 직접 테스트
Ubuntu의 dig 명령은 dnsutils 패키지에 포함되어 있습니다. 먼저 주소를 직접 지정해 조회하면 ‘코어 DNS 자체의 오류’와 ‘시스템 요청이 코어로 전달되지 않는 문제’를 구분할 수 있습니다.
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
dig @127.0.0.1 -p 1053 example.com AAAA
응답 상태와 답변 레코드, 시간 초과 여부를 확인하세요. fake-ip 모드에서 A 레코드를 조회해도 코어가 가상 주소를 할당할 수 있다는 점만 확인될 수 있으며, 실제 업스트림 조회 성공까지 입증되지는 않습니다. 실제 접속을 시도하고 로그도 함께 확인하세요. dns.ipv6: false로 설정했다면 AAAA 조회에서 주소가 반환되지 않아도 반드시 오류인 것은 아닙니다.
3단계: 시스템 DNS 경로와 서비스 연결 확인
resolvectl query example.com
curl -I --connect-timeout 10 https://example.com
curl -I --connect-timeout 10 --proxy http://127.0.0.1:7890 https://example.com
마지막 명령은 기존 설정의 mixed-port가 7890이라고 가정하고 명시적인 HTTP 프록시를 통해 HTTPS 터널을 만듭니다. 이 명령만으로 시스템 DNS가 가로채졌다고 입증할 수는 없습니다. 두 번째 명령은 환경 변수에 설정된 프록시의 영향을 받을 수도 있으므로 결과를 비교하기 전에 터미널 환경을 확인하세요. 명시적 프록시로는 접속되는데 일반 앱에서 실패한다면 시스템 프록시 적용 범위, TUN 라우팅, 앱 자체 DNS를 중점적으로 살펴보세요.
4단계: 캐시를 비우고 설정을 하나씩 되돌리기
sudo resolvectl flush-caches
systemd-resolved 캐시를 비운 뒤 브라우저를 완전히 종료하고 다시 여세요. 브라우저 자체 DNS 캐시와 기존 연결 풀은 시스템 캐시와 함께 비워지지 않을 수 있습니다. 잠시 코어 로그 수준을 높여 DNS 시간 초과, 노드 도메인 조회 실패, 규칙 매칭을 살펴본 다음 원래 로그 수준으로 되돌리세요. 로그에는 방문한 도메인이 포함될 수 있으므로 공유하기 전에 구독 주소, 인증 정보, 개인 접속 기록을 삭제하세요.
자주 발생하는 증상과 최소 변경 원칙
| 증상 | 먼저 확인할 항목 | 다음 조치 |
|---|---|---|
| 1053 포트 직접 조회 시간 초과 | 리스닝 주소, 포트 충돌, 코어 실행 여부 | 먼저 ss와 실행 로그를 확인한 뒤 업스트림 연결을 점검하세요. |
| 198.18로 시작하는 주소가 반환되지만 접속되지 않음 | fake-ip 후속 트래픽과 주소 매핑 | TUN 라우팅을 확인하고 캐시를 비운 뒤 다시 연결하세요. |
| 특정 도메인만 접속되지 않음 | fallback-filter, nameserver-policy, 도메인 규칙 | 해당 도메인에만 적용된 정책을 일시적으로 해제하고 로그를 비교하세요. |
| 노드 목록은 보이지만 모두 연결 실패 | 노드 도메인 조회와 노드 자체의 연결 가능 여부 | proxy-server-nameserver 설정과 노드 연결 오류를 확인하세요. |
| 브라우저에서만 다르게 나타남 | 보안 DNS, 확장 프로그램 프록시, 브라우저 캐시 | 조회 경로를 일시적으로 통일하고 브라우저를 다시 시작한 뒤 테스트하세요. |
| 구독 업데이트 후 문제가 다시 발생 | 클라이언트 덮어쓰기와 생성된 설정 | 수정 사항을 클라이언트에서 지원하는 지속형 덮어쓰기 방식으로 적용하세요. |
안정적으로 설정을 조정하려면 먼저 DNS 리스너 하나에서 조회가 되는지 확인하고, 업스트림 하나에 연결할 수 있는지 검증하세요. 다음으로 시스템 요청과 서비스 연결이 코어를 통과하는지 확인한 뒤 fallback, 도메인별 DNS 정책, TUN 가로채기 규칙을 추가합니다. 매번 변수 하나만 바꾸고 변경 전후의 조회 결과를 기록하세요. 그래야 문제가 DNS 조회, 라우팅, 노드 중 어디에서 비롯됐는지 구분할 수 있고 모든 증상을 ‘DNS 오염’으로 치부하지 않을 수 있습니다.
포트, 프록시 그룹, 규칙의 전체적인 관계를 알아보려면 입문 가이드를 읽어 보세요. 설정 필드를 확인할 때는 프로토콜 레퍼런스를 참고할 수 있습니다. 이 글의 DNS 및 TUN 설정은 모두 기존 설정에 병합하고 원래 노드와 규칙을 유지하세요. 구독 설정 전체를 덮어쓰지 마세요.