Clash DNS 누수 확인 및 해결: 테스트 결과 해석과 fake-ip·nameserver-policy 설정
DNS 누수 테스트 결과를 해석하고 fake-ip와 redir-host의 차이를 비교합니다. nameserver, fallback, nameserver-policy 설정으로 DNS 요청 경로를 관리하는 방법도 살펴봅니다.
1. 먼저 DNS 누수 판단 기준부터 확인하기
브라우저에 프록시 출구 IP가 표시된다고 해서 도메인 조회도 같은 경로를 거친다는 뜻은 아닙니다. 웹사이트에 접속할 때는 도메인을 조회하는 DNS 요청과 대상 서버에 연결하는 트래픽이 각각 발생합니다. Clash 시스템 프록시, TUN 가로채기, 코어 DNS, 브라우저 보안 DNS는 서로 다른 단계에 적용되므로 문제를 점검할 때 각각 나눠 살펴봐야 합니다.
이 글에서 ‘DNS 누수’란 지정된 리졸버나 프록시 경로로 보내야 할 DNS 조회가 예상하지 못한 리졸버로 전송되는 경우를 말합니다. 예를 들어 해외 웹사이트 도메인은 프록시를 통해 조회하도록 설정했는데, 테스트에서 현지 인터넷 서비스 제공업체의 재귀 DNS가 계속 나타난다면 원인을 확인해야 합니다. 반대로 로컬 도메인은 원래 현지 리졸버로 조회하도록 설정했다면 해당 결과가 나타나는 것은 이상하지 않습니다.
기대하는 경로를 먼저 정한 다음 테스트 결과를 확인하세요. 로컬에서 조회해도 되는 도메인과 프록시를 통해 조회해야 하는 도메인은 무엇인지, 브라우저가 자체적으로 DoH를 사용할 수 있는지 정리해야 합니다. 이 기준 없이 ‘몇 개 국가가 감지됐는지’만으로는 누수 여부를 판단할 수 없습니다.
DNS 테스트 페이지에서 확인할 수 있는 항목
| 테스트 항목 | 확인할 수 있는 내용 | 이것만으로 단정할 수 없는 내용 |
|---|---|---|
| 웹사이트 출구 IP | 현재 웹 연결에 표시되는 외부 IP 주소 | 시스템의 모든 앱이 프록시를 거친다는 사실 |
| DNS 서버 IP | 테스트 도메인의 권한 서버에서 관찰한 재귀 리졸버의 출구 IP | 기기에서 직접 연결한 DNS 상위 서버가 해당 주소라는 사실 |
| 국가 및 인터넷 서비스 제공업체 | IP 주소 데이터베이스에 따른 소속 정보 | DNS 요청이 실제로 거친 모든 네트워크 경로 |
| 여러 리졸버가 표시됨 | 병렬 조회, 클러스터 출구 또는 복수 상위 서버일 수 있음 | 개수가 1개보다 많으면 반드시 누수라는 판단 |
공용 DNS는 대개 Anycast와 분산 재귀 클러스터를 사용합니다. 클라이언트가 연결하는 서비스 주소와 테스트 페이지에 표시되는 재귀 출구 주소가 다를 수 있고, 국가 정보도 최신 상태가 아닐 수 있습니다. 따라서 프록시 출구는 일본인데 DNS 결과가 미국으로 표시된다는 사실만으로 누수라고 단정할 수는 없습니다. DNS 제공업체, 설정된 상위 서버, 실제 연결 로그를 함께 확인하세요.
2. 정해진 절차로 재검사해 시스템과 브라우저 구분하기
먼저 현재 코어 이름과 클라이언트 버전, 활성 설정, 프록시 모드, 시스템 프록시 및 TUN 상태를 기록하세요. 아래 설정은 mihomo 기준이며, 구형 Clash 코어에서는 일부 항목을 지원하지 않을 수 있습니다. Clash Nyanpasu 버전에 따라 설정 메뉴 구성이 달라질 수 있으므로 옵션을 찾을 수 없다면 구독 원본만 보지 말고 최종 적용된 설정을 확인하세요.
- 기준 결과 기록: 직접 연결 테스트를 허용하는 네트워크에서 시스템 프록시와 TUN을 끈 뒤 DNS 테스트를 실행하고, 웹 출구 IP와 리졸버 IP, 서비스 제공업체를 기록합니다. DNS 조회 프라이버시를 엄격하게 지켜야 한다면 직접 연결 기준 테스트는 건너뛰어도 됩니다.
- 시스템 프록시만 켜기: 브라우저 설정은 그대로 둔 채 다시 테스트합니다. 시스템 프록시는 프록시 설정을 따르는 앱에 주로 적용되며, 시스템의 UDP 53 요청까지 가로채는 것은 아닙니다.
- TUN과 DNS 가로채기 켜기: 코어가 정상적으로 시작됐는지 확인한 뒤 다시 테스트합니다. 이 단계에서만 결과가 달라진다면 앞서 코어를 거치지 않은 DNS 트래픽부터 확인하세요.
- 브라우저 DNS를 임시로 통일하기: 원래 설정을 기록한 뒤 브라우저의 보안 DNS를 잠시 끄고 다시 테스트합니다. Chrome에서는 ‘설정’ → ‘개인 정보 보호 및 보안’ → ‘보안’에서 ‘보안 DNS 사용’을 찾을 수 있습니다. 조직 정책에 따라 이 옵션이 잠겨 있을 수 있습니다.
- 두 차례 반복: 이전 결과 페이지를 새로고침하는 데 그치지 말고 매번 테스트를 새로 실행합니다. 필요하면 캐시를 지우고 브라우저를 다시 시작해 과거 조회 결과를 현재 경로로 오인하지 않도록 하세요.
브라우저 DoH는 HTTPS를 통해 도메인을 조회합니다. mihomo의 DNS 모듈을 우회할 수 있지만, 이때 사용하는 HTTPS 연결은 프록시나 TUN을 거칠 수 있습니다. 따라서 ‘코어 DNS를 우회한다’는 것과 ‘조회 요청을 현지 인터넷 서비스 제공업체로 직접 보낸다’는 것은 같은 의미가 아니므로 따로 확인해야 합니다.
명령어로 코어 DNS 응답 확인하기
코어 DNS가 127.0.0.1:1053에서 수신 대기한다고 가정하면 아래 명령어로 직접 조회할 수 있습니다. Windows PowerShell에서 캐시를 지우려면 시스템 권한이 필요할 수 있습니다. dig가 설치된 시스템에서는 두 번째 명령어를 사용할 수 있습니다. 여기서 example.com은 진단용 도메인이며 프록시 노드가 아닙니다.
# Windows PowerShell: 시스템 DNS 캐시 지우기
Clear-DnsClientCache
# dig가 설치된 macOS / Linux: 코어 DNS에 직접 조회
dig @127.0.0.1 -p 1053 example.com A
# IPv6 레코드도 조회해 결과를 각각 확인
dig @127.0.0.1 -p 1053 example.com AAAA
fake-ip 모드에서 일반 A 레코드를 조회하면 198.18.0.0/16 범위의 주소가 반환될 수 있습니다. 이는 대개 정상적인 매핑이며 DNS 변조가 아닙니다. fake-ip 제외 규칙, 특정 도메인 처리 방식 또는 캐시 상태에 따라 결과가 달라질 수 있습니다. 명령어 조회에 성공했다는 사실은 해당 수신 대기 포트가 작동한다는 뜻일 뿐, 브라우저나 시스템의 기본 DNS가 그 주소를 사용한다는 증거는 아닙니다.
3. fake-ip와 redir-host: 차이는 조회 시점
| 모드 | 앱에 반환되는 주소 | 주요 점검 항목 |
|---|---|---|
| fake-ip | 일반 조회에 가상 주소를 반환하고 코어가 도메인 매핑을 관리함 | 이후 연결이 코어로 돌아와야 하며 제외 목록은 최소한으로 유지해야 함 |
| redir-host | 대개 상위 서버에서 조회한 실제 주소를 반환함 | 상위 서버의 조회 품질, 도메인 연관성 및 IP 규칙 일치 여부 |
fake-ip에서는 앱의 연결 요청을 받은 코어가 가상 주소를 통해 도메인을 찾아 규칙에 따라 출구를 결정합니다. 원격 프록시에서 대상 도메인을 조회하는 연결은 로컬에서 대상의 실제 IP를 미리 알아야 할 필요가 없을 수 있습니다. 하지만 직접 연결, IP 규칙 판정, 일부 프로토콜에서는 여전히 조회가 필요할 수 있습니다. fake-ip는 ‘켜기만 하면 모든 DNS가 자동으로 프록시를 거치는’ 기능이 아닙니다.
redir-host는 실제 주소를 조회하는 기존 방식에 더 가깝습니다. 신뢰할 수 있는 암호화 상위 서버와 함께 사용할 수 있으며, 이 모드를 쓴다는 이유만으로 누수가 발생한다고 볼 수는 없습니다. 모드를 고를 때는 이름을 프라이버시 등급처럼 여기지 말고 앱 호환성, 연결이 온전히 가로채지는지, 규칙 요구사항을 기준으로 판단하세요.
특정 앱 문제를 해결하려고 제외 범위를 넓히지 마세요
특정 LAN 서비스, 게임 또는 기기 검색 기능이 fake-ip와 호환되지 않는다면 해당 도메인만 fake-ip-filter에 설정하세요. 처음부터 널리 쓰이는 공용 도메인 접미사를 통째로 제외하지 마세요. 제외 범위가 넓을수록 더 많은 요청이 실제 주소 조회 경로로 돌아가며, 가상 매핑에 의존하던 동작도 달라집니다. 모드를 전환한 뒤에는 관련 앱을 다시 시작해 이전 가상 주소가 캐시에 남지 않도록 하세요.
4. nameserver, fallback, 도메인별 DNS 설정
먼저 세 항목의 역할을 구분하세요. nameserver는 기본 조회에 사용할 상위 서버, nameserver-policy는 지정한 도메인에 사용할 상위 서버, fallback은 필터 조건과 함께 조회 결과를 선택하는 데 쓰입니다. 이 항목들은 ‘어느 서버에 물어볼지’를 정할 뿐, ‘어떤 출구를 통해 연결할지’까지 자동으로 정하지는 않습니다. 암호화 DNS는 전송 방식을, 프록시 라우팅은 연결 경로를 정하므로 각각 설정해야 합니다.
검증 가능한 DNS 기준 설정부터 만들기
아래 DNS 설정 조각을 기존 설정에 병합해 사용하세요. 전체 구독 설정이 아닙니다. IP 형식의 DoH 주소를 사용하면 상위 서버 도메인을 먼저 조회해야 하는 의존성을 줄일 수 있습니다. 네트워크에서 지정한 서비스를 직접 연결할 수 없다면 프록시 경로를 추가로 설정하세요. 시간 초과를 YAML 파싱 오류로 오해하지 않도록 주의하세요.
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
nameserver:
- https://1.1.1.1/dns-query
fake-ip-filter:
- "*.lan"
- "*.local"
default-nameserver는 주로 DNS 상위 서버의 도메인을 조회하는 데 사용되며, 모든 대상 도메인을 이 서버에 맡긴다는 뜻은 아닙니다. 여기서223.5.5.5는 암호화되지 않은 부트스트랩 리졸버입니다. 부트스트랩 조회까지 암호화해야 한다면 현재 코어에서 지원하고 접속 가능한 암호화 부트스트랩 상위 서버를 사용하고 실제로 작동하는지 확인하세요.listen은 루프백 주소에서만 수신 대기하므로 이 예시가 LAN에 공개된 DNS 서비스로 바뀌지 않게 합니다. 시스템 DNS 설정에서는 보통 1053 같은 사용자 지정 포트를 지정할 수 없으므로 가로채기 기능이나 로컬 포트 전달이 필요합니다.ipv6: false는 코어 DNS의 AAAA 응답을 제어할 뿐, 운영체제의 IPv6를 끄거나 앱이 이미 알고 있는 IPv6 주소로 접속하는 것을 막지는 않습니다. IPv6 연결은 라우팅 또는 TUN에서 올바르게 처리해야 합니다.
nameserver-policy로 LAN과 공용 도메인 분리하기
아래 설정 조각은 하나의 dns 객체 안에 넣으세요. 예시에서는 라우터 DNS가 192.168.1.1이라고 가정합니다. 실제 주소는 현재 네트워크에서 확인해야 합니다. PROXY는 기존 설정에 실제로 존재하는 정책 그룹 이름이어야 하며 대소문자도 일치해야 합니다. 그렇지 않다면 적용 전에 실제 그룹 이름으로 바꾸세요.
nameserver-policy:
"+.lan":
- 192.168.1.1
"+.github.com":
- "https://1.1.1.1/dns-query#PROXY"
+.github.com은 해당 도메인과 모든 하위 도메인에 일치합니다. 따옴표 안의 #PROXY는 mihomo에서 DNS 상위 서버의 출구를 지정하는 문법으로, 이 DoH 연결이 지정된 정책을 사용하게 합니다. 해당 그룹에서 DIRECT를 선택하면 요청은 여전히 직접 연결됩니다. 사용할 수 없는 노드를 선택하면 시간 초과가 발생합니다. 정책별 조회는 목록에 지정한 도메인에만 적용되며 모든 공용 웹사이트에 자동으로 적용되지는 않습니다.
fake-ip 제외 목록과 정책별 조회는 서로 다른 기능입니다. 전자는 가상 주소를 반환할지 실제 주소로 조회할지에 영향을 주고, 후자는 사용할 조회 상위 서버를 선택합니다. *.lan을 제외 목록에 추가했다면 해당 LAN 리졸버가 실제로 그 레코드를 알고 있는지도 확인해야 합니다.
fallback은 단순한 시간 초과 대체 서버가 아닙니다
fallback을 설정하면 코어가 여러 서버에 병렬로 조회하고 fallback-filter에 따라 사용할 결과를 선택할 수 있습니다. 기본 리졸버가 작동하는 동안에는 fallback으로 도메인 조회가 절대 전달되지 않는다고 생각하면 안 됩니다. 아래 예시는 GeoIP 데이터를 활용해 결과를 필터링하는 한 가지 방법만 보여 주며, 앞서 제시한 최소 설정과 함께 활성화할 필요는 없습니다.
fallback:
- https://8.8.8.8/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
이 예시는 GeoIP의 CN 판정과 지정된 IP 대역 필터를 이용해 결과를 선택합니다. 데이터베이스가 오래됐거나 CDN 주소의 소속 지역이 바뀌면 선택 결과가 달라질 수 있습니다. fallback도 기본 프록시 경로가 아닙니다. HTTPS 연결은 실제로 설정된 출구를 따릅니다. 조회 정보를 받는 서버의 범위를 줄이려면 먼저 단일 상위 서버로 문제를 확인한 다음 fallback을 추가할 필요가 있는지 판단하세요.
5. TUN 가로채기와 DNS 출구: 두 경로 모두 확인하기
첫 번째 경로는 앱에서 코어까지, 두 번째 경로는 코어에서 상위 서버까지입니다. dns.enable만 설정한다고 모든 앱이 자동으로 코어 DNS를 사용하지는 않습니다. TUN을 켠 경우에도 DNS 가로채기가 실제로 작동하는지 확인해야 합니다. 아래는 일반적인 mihomo TUN 설정 예시입니다. 사용하기 전에 클라이언트에 필요한 시스템 권한이 있는지, 다른 VPN과 라우팅 충돌이 없는지 확인하세요.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
이 설정이 가로채는 것은 TUN으로 들어오는 일반 UDP/TCP 53 트래픽입니다. 브라우저 DoH는 보통 HTTPS 443을, DoT는 일반적으로 853을 사용하므로 53번 포트를 가로채도록 설정해도 코어 DNS로 자동 전달되지 않습니다. 일부 시스템의 LAN 라우팅, 인터페이스 바인딩, 다중 네트워크 어댑터 동작도 가로채기에 영향을 줄 수 있으므로 로그와 재검사로 확인해야 합니다.
DNS가 라우팅 규칙을 따르게 하려면
mihomo의 respect-rules를 사용하면 DNS 상위 서버 연결에 라우팅 규칙을 적용할 수 있습니다. 이 옵션을 켤 때는 프록시 노드 도메인을 별도로 조회할 수 있도록 proxy-server-nameserver도 설정해야 합니다. 그렇지 않으면 ‘프록시에 연결해야 조회할 수 있는데, 연결하려면 먼저 조회해야 하는’ 순환 의존성이 생길 수 있습니다.
respect-rules: true
proxy-server-nameserver:
- https://1.1.1.1/dns-query
이 두 줄도 dns 객체에 넣어야 합니다. 예시의 노드 도메인 조회 서버는 프록시 연결이 아직 성립되지 않은 상태에서도 접속할 수 있어야 합니다. 현재 네트워크에서 직접 연결할 수 없다면 접근 가능한 서버로 바꾸고 그에 따른 조회 정보 노출 범위도 고려하세요. 연결할 수 없는 프록시 그룹 하나에 모든 DNS 상위 서버를 억지로 지정하지 마세요.
설정을 병합할 때 최상위 dns 키는 하나만 유지하세요. 같은 이름의 섹션을 여러 개 이어 붙이지 마세요. 구독을 업데이트하면 수동 변경 사항이 덮어써질 수 있으므로 클라이언트에서 지원하는 재정의 또는 병합 기능으로 저장하고 다시 불러온 뒤 최종 설정을 확인하세요. 메뉴 위치는 클라이언트 버전에 따라 다를 수 있습니다. 사용 방법은 사용 가이드에서 확인하세요.
6. 증상별 원인 확인 및 최종 재검사
| 증상 | 먼저 확인할 항목 | 다음 조치 |
|---|---|---|
| 웹은 프록시를 거치는데 현지 인터넷 서비스 제공업체 DNS가 계속 표시됨 | 시스템 DNS가 가로채지 않았거나 부트스트랩 조회와 정책이 직접 연결됨 | TUN, 53번 포트 가로채기, 각 상위 서버의 출구를 확인 |
| 특정 브라우저에서만 다른 리졸버가 표시됨 | 브라우저 보안 DNS, 확장 프로그램 또는 별도 프록시 설정 | 설정을 임시로 통일하고 다시 테스트 |
| respect-rules를 켠 뒤 모든 조회가 시간 초과됨 | 노드 도메인 조회 순환, 잘못된 그룹 이름 또는 연결할 수 없는 상위 서버 | 먼저 proxy-server-nameserver에 연결할 수 있는지 확인 |
| LAN 도메인이 작동하지 않음 | 공용 상위 서버가 내부 네트워크 레코드를 알지 못함 | 정확한 정책을 추가하고 필요한 경우 fake-ip 제외 설정 |
| IPv6 DNS를 껐는데도 IPv6 연결이 보임 | 앱 캐시, 하드코딩된 주소 또는 시스템 IPv6 라우팅 | 캐시를 지우고 IPv6 트래픽이 가로채지는지 확인 |
로그를 확인할 때는 방금 실행한 조회를 중심으로 다음 세 가지를 살펴보세요. 코어가 요청을 받았는지, 어떤 상위 서버를 선택했는지, 그 상위 서버 연결이 어떤 정책으로 나갔는지 확인합니다. DoH 요청은 연결 목록에서 보통 DNS 서비스로 향하는 HTTPS 연결로 표시됩니다. 443 연결 하나만 보고 웹사이트 트래픽이 잘못된 출구로 나간다고 단정할 수는 없습니다. 필요하면 잠시 로그 수준을 높이고 점검이 끝나면 원래대로 되돌리세요. 로그를 공유하기 전에는 구독 주소, 인증 정보, 개인 도메인을 삭제하세요.
- 설정을 저장한 뒤 코어를 다시 불러와 알 수 없는 필드, YAML 들여쓰기 오류, 포트 사용 충돌이 없는지 확인하세요.
dig @127.0.0.1 -p 1053으로 DNS 수신 대기를 확인한 다음 실제 브라우저로 접속해 전체 경로가 가로채지는지 검증하세요.- DNS 테스트를 반복하고 일반 창, 다른 브라우저, IPv4 및 IPv6 결과를 각각 기록하세요.
- 브라우저 보안 DNS와 앱, 네트워크 환경을 하나씩 원래대로 복원해 결과를 바꾸는 설정을 찾아내세요.
- 클라이언트를 다시 시작하거나 구독을 한 번 업데이트한 뒤 재검사해 설정 덮어쓰기가 유지되는지 확인하세요. 현재 실행 중에만 적용되는 설정이어서는 안 됩니다.
최종 목표는 테스트 페이지에 주소 하나만 표시되게 하는 것이 아닙니다. 각 조회가 미리 정한 경로를 따르게 하는 것입니다. LAN 도메인은 내부 리졸버에 맡기고, 프록시가 필요한 도메인은 지정된 정책으로 조회하며, 노드 도메인에는 사용할 수 있는 부트스트랩 경로를 마련해야 합니다. 가로채기, 상위 서버, 출구를 각각 검증하면 fake-ip와 redir-host를 반복해서 바꾸는 것보다 문제를 더 쉽게 찾을 수 있습니다.