1. DNS 누수 판단: 먼저 프록시를 거쳐야 하는 요청을 확인하세요

웹사이트 접속 IP가 프록시 주소로 바뀌었더라도 DNS 요청은 여전히 로컬 네트워크로 전송될 수 있습니다. 웹 연결과 도메인 조회는 서로 다른 경로를 사용하기 때문입니다. 시스템 프록시는 보통 프록시 설정을 따르는 앱에만 적용되며, 시스템이 UDP 53 포트로 보내는 요청까지 자동으로 처리하지 않습니다. 브라우저가 자체 암호화 DNS를 사용할 수도 있습니다.

이 글에서 말하는 ‘누수’는 프록시를 거쳐야 할 도메인 조회가 실수로 로컬 직접 연결을 통해 DNS 서버에 전송되는 경우입니다. 국내 도메인은 로컬 DNS로 조회하도록 설정했다면 이는 의도된 동작입니다. 테스트 페이지에 DNS 서버가 두 곳 표시된다는 이유만으로 설정이 잘못됐다고 판단하지 마세요.

확인된 현상의미다음 단계
웹 접속 IP가 프록시 노드로 표시됨해당 웹 연결은 프록시를 통과함DNS 요청 경로 확인
테스트에 로컬 통신사 DNS가 표시됨로컬 재귀 DNS 조회 가능성이 있음분할 라우팅 정책과 패킷 캡처 결과 확인
테스트에 공용 DNS 제공업체가 표시됨해당 제공업체가 재귀 조회에 관여함이름만으로 프록시 경유 여부를 판단할 수 없음
조회 결과가 198.18.x.x로 반환됨fake-ip 매핑이 적용됐을 수 있음상위 DNS 조회와 연결 라우팅을 추가로 확인

2. DNS 누수 테스트: 기준 결과, 비교, 패킷 캡처

먼저 테스트 조건을 고정하세요

  1. 클라이언트 이름과 버전, 커널 버전을 기록하세요. 아래 설정은 mihomo 기준입니다. 원본 Clash나 구형 커널에서는 일부 필드를 지원하지 않을 수 있습니다.
  2. 현재 프록시 모드와 노드, TUN 사용 여부, 브라우저 보안 DNS 설정을 기록하세요. 테스트 중에는 노드와 DNS 서버를 동시에 바꾸지 마세요.
  3. 같은 네트워크에서 먼저 프록시를 끄고 DNS 누수 테스트를 실행한 뒤 DNS 서버 이름과 IP, 웹 접속 IP를 기록하세요. 이 결과를 직접 연결 기준값으로 삼습니다.
  4. 프록시를 켠 다음 테스트 페이지에서 새 테스트를 실행하세요. 캐시 영향을 줄이려면 임의의 서브도메인을 생성하는 테스트 기능을 우선 사용하세요.
  5. 이어서 TUN을 켜고 같은 테스트를 반복하세요. TUN을 켰을 때만 결과가 달라진다면, 시스템 DNS가 이전에 커널을 우회했는지 먼저 확인하세요.

캐시를 비운 다음 로컬 DNS 리스너 확인

Windows에서는 터미널에서 아래 명령을 실행할 수 있습니다. 첫 번째 명령은 시스템 캐시를 비우고, 두 번째 명령은 이 글의 설정에서 사용하는 로컬 DNS 리스너를 조회합니다. 브라우저에도 자체 캐시와 연결 풀이 있으므로 테스트할 때는 브라우저를 완전히 종료한 뒤 다시 실행하세요. 페이지 새로고침만으로는 새 DNS 조회가 발생하지 않을 수 있습니다.

ipconfig /flushdns
nslookup example.com 127.0.0.1

아래 예제는 127.0.0.1:1053에서 수신하지만, 위의 nslookup은 기본적으로 53 포트를 조회합니다. 따라서 로컬에 53 포트 포워딩이 설정된 경우에만 사용할 수 있습니다. 1053 포트를 확인하려면 설치된 dig처럼 포트를 지정할 수 있는 도구를 사용하세요.

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA

가짜 IP가 반환되면 이번 조회가 커널 DNS로 들어갔다는 뜻입니다. 모든 앱이 이 경로를 사용한다는 의미는 아닙니다. 클라이언트 연결 기록에서 대상 도메인에 적용된 규칙과 아웃바운드 정책도 확인하세요.

패킷 캡처로 로컬 경로 확인

실제로 인터넷에 연결된 물리 네트워크 어댑터에서 패킷을 캡처하고 udp.port == 53 || tcp.port == 53 필터를 적용한 뒤 테스트를 다시 실행하세요. 테스트용 임의 도메인이 라우터나 통신사 DNS로 직접 전송된 것이 보이고, 예상된 직접 연결 정책에 해당하지 않는다면 우회가 발생했다는 명확한 증거입니다. 패킷 캡처에는 도메인 등 개인정보가 포함될 수 있으므로 공유하기 전에 반드시 가리세요.

DoH는 보통 TCP 443 또는 QUIC 443을 사용하고, DoT는 일반적으로 TCP 853을 사용합니다. 53 포트 트래픽이 없다고 DNS 우회가 없다는 뜻은 아닙니다. 암호화된 요청은 대상 DNS 서버 IP와 프로세스, 클라이언트 연결 로그를 함께 확인해야 합니다.

3. fake-ip, DNS 정책, TUN 가로채기의 역할

방식실제 역할한계
fake-ip도메인에 가짜 IP를 할당해 커널이 도메인을 복원하고 규칙을 적용할 수 있도록 함앱에 내장된 DoH를 자동으로 가로채지는 않음
nameserver-policy도메인별로 DNS 서버를 선택DNS 서버 선택이 프록시 아웃바운드 지정과 같은 것은 아님
respect-rulesDNS 상위 서버 연결에 라우팅 규칙을 적용규칙이 직접 연결로 적용되면 상위 서버도 직접 연결됨
TUN의 dns-hijackTUN을 통과하는 대상 DNS 트래픽을 커널에서 처리임의의 HTTPS 트래픽 내부에 있는 DNS를 복호화하거나 바꿀 수 없음

198.18.0.0/16은 fake-ip에 흔히 사용하는 범위로, 벤치마크용으로 예약된 주소 공간입니다. 프록시 노드의 실제 공인 IP가 아닙니다. 앱이 이 가짜 IP에 연결하면 커널이 매핑을 통해 도메인을 복원한 뒤 규칙을 적용하고 연결을 처리합니다.

따라서 fake-ip는 도메인 매핑 방식이지, ‘모든 DNS를 프록시로 보내는’ 만능 스위치가 아닙니다. 제대로 설정하려면 세 가지 경로를 모두 확인해야 합니다. 앱이 DNS 요청을 어디로 보내는지, 커널이 어떤 DNS 서버를 선택하는지, 해당 DNS 서버에 연결할 때 어떤 경로를 사용하는지 확인하세요.

4. mihomo DNS 설정: 검증 가능한 기본 설정 구성

먼저 현재 설정을 백업하세요. 아래 내용을 해당 필드를 지원하는 mihomo 설정에 병합하고 기존 노드, 정책 그룹, 규칙은 유지하세요. 완전한 구독 파일처럼 통째로 가져오면 안 됩니다. 이름이 같은 dns: 섹션은 하나만 남겨야 하며 YAML 들여쓰기에는 공백을 사용하세요.

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "*.lan"
    - "*.local"
  respect-rules: true
  default-nameserver:
    - 223.5.5.5
  proxy-server-nameserver:
    - https://223.5.5.5/dns-query
  nameserver:
    - https://1.1.1.1/dns-query

설정 적용 여부만 보지 말고 항목별로 확인하세요

  • listen은 로컬 루프백 주소에만 바인딩해 DNS 서비스를 LAN에 공개하지 않도록 합니다. 시스템 네트워크 설정에는 보통 DNS 포트 1053을 지정할 수 없습니다. 연결하려면 TUN 가로채기나 로컬 포워딩이 필요합니다.
  • ipv6: false는 커널 DNS의 AAAA 조회 처리를 제어합니다. 운영체제의 IPv6를 끄는 설정이 아니며, 앱이 다른 방법으로 IPv6 주소를 얻는 것도 막지 못합니다.
  • default-nameserver는 DNS 서버 자체의 도메인을 조회하는 데 사용됩니다. 예제에는 암호화되지 않은 부트스트랩 DNS가 남아 있으므로 모든 조회가 암호화된다고 할 수는 없습니다. IP 주소 형식의 DoH 주소를 사용하면 관련 부트스트랩 조회를 줄일 수 있습니다.
  • proxy-server-nameserver는 프록시 서버의 도메인을 조회해 ‘프록시에 연결해야 프록시 주소를 조회할 수 있는’ 순환 의존성을 줄입니다. 예제에서는 별도의 DoH 서버를 사용하지만, 현재 네트워크에서 접속 가능한지는 직접 테스트해야 합니다.
  • respect-rules: true를 사용하려면 정상적으로 동작하는 프록시 서버 DNS 설정이 필요합니다. 1.1.1.1:443 연결이 의도한 프록시 정책을 적용받는지도 확인하세요. 기존 규칙에서 직접 연결로 처리한다면 DNS 조회는 여전히 프록시를 통과하지 않습니다.

적용 후에는 설정 검사 결과와 실행 로그를 차례로 확인하세요. 알 수 없는 필드가 표시되면 새 필드를 계속 구형 커널에 추가하지 말고 실제로 로드된 커널부터 확인하세요. 클라이언트의 UI 설정이 구독 DNS 섹션을 덮어쓸 수 있고, 구독 업데이트가 수동 변경을 되돌릴 수도 있습니다. 클라이언트의 영구 오버라이드 기능을 사용하고 최종 적용 설정을 확인하세요.

5. nameserver-policy: LAN 도메인에 별도 DNS 서버 지정

회사 인트라넷, 홈 NAS, 라우터 관리 도메인은 로컬 DNS에서만 조회되는 경우가 많습니다. 이를 모두 공용 DNS에 보내면 보안이 강화되기보다 도메인을 찾지 못하는 경우가 일반적입니다. 아래는 도메인별 DNS 조회를 명시하는 예입니다. 라우터 주소가 실제로 192.168.1.1이고 해당 도메인을 조회할 수 있을 때만 사용하세요.

  nameserver-policy:
    "+.lan":
      - 192.168.1.1
    "+.home.arpa":
      - 192.168.1.1

이 설정을 기존 dns: 아래에 추가하고 nameserver와 같은 들여쓰기 단계에 배치하세요. 여기서는 두 칸 들여쓰기가 중요합니다. +.lan은 해당 도메인과 하위 도메인을 모두 매칭하고, home.arpa는 홈 네트워크 전용 도메인입니다. 내부 서비스 하나를 복구하려고 공용 도메인 접미사를 통째로 로컬 DNS에 맡기지 마세요.

앱이 내부망의 실제 주소를 받아야 한다면 해당 도메인을 기존 fake-ip-filter에도 추가하세요. 예를 들면 "*.home.arpa"입니다. 필터는 가짜 IP 반환 방식만 바꾸며 DNS 서버를 선택하거나 직접 연결 경로를 지정하지 않습니다. LAN 대역에는 여전히 올바른 직접 연결 규칙이 필요합니다.

테스트할 때는 먼저 내부망 서비스를 조회하고 다음으로 공용 도메인을 조회하세요. 내부망 조회가 라우터로 직접 연결되는 것은 이 정책에서 의도된 동작입니다. 공용 도메인의 예상치 못한 우회와 혼동하지 마세요.

6. TUN DNS 가로채기: 시스템 조회와 시스템 프록시를 따르지 않는 앱 처리

시스템 프록시만 켜면 일부 앱은 자체적으로 DNS 요청을 보낼 수 있습니다. 데스크톱 mihomo 클라이언트는 TUN으로 처리 범위를 넓힐 수 있으며, 보통 서비스 모드나 관리자 권한이 필요합니다. 아래는 앞서 설명한 DNS 설정과 함께 사용할 수 있는 기본 예제입니다.

tun:
  enable: true
  stack: system
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53

any:53은 TUN을 통과하는 UDP DNS를 매칭하고, 다음 항목은 TCP DNS를 처리합니다. 핵심은 트래픽이 실제로 TUN에 들어와야 한다는 점입니다. 다른 VPN, 가상 머신 브리지, 컨테이너 네트워크, IPv6 라우팅, 앱 제외 목록이 별도의 경로를 만들 수 있습니다. 일부 시스템에서는 로컬 네트워크 DNS를 가로채는 데 제한이 있으므로 실제 패킷 캡처 결과를 기준으로 판단하세요.

브라우저 보안 DNS는 별도로 테스트하세요

Chrome에서는 ‘설정’ → ‘개인정보 보호 및 보안’ → ‘보안’ → ‘보안 DNS 사용’에서 현재 옵션을 확인할 수 있습니다. 버전에 따라 메뉴 이름이 조금 다를 수 있습니다. 문제를 진단할 때는 먼저 이 옵션을 끄고 브라우저가 시스템 DNS를 사용하도록 한 뒤 TUN을 테스트하세요. 그런 다음 옵션을 다시 켜고 브라우저의 DNS 서버 연결에 의도한 프록시 규칙이 적용되는지 확인하세요.

암호화 DNS를 계속 꺼 두라는 뜻은 아닙니다. 변수별로 원인을 구분하기 위한 절차입니다. 앱에 내장된 DoH는 일반적인 암호화 네트워크 연결이므로 53 포트 가로채기를 설정해도 자동으로 대체되지 않습니다. Android의 ‘비공개 DNS’도 별도로 확인해야 합니다. 보통 ‘설정’ → ‘네트워크 및 인터넷’ → ‘비공개 DNS’에서 찾을 수 있지만, 제조사별 UI에 따라 위치가 달라질 수 있습니다.

7. 자주 발생하는 문제와 최종 점검 목록

fake-ip를 켠 뒤 프린터나 NAS에 연결할 수 없음

먼저 내부망 도메인을 어느 DNS 서버가 조회하는지 확인한 뒤 정확한 nameserver-policy와 필요한 fake-ip 필터를 추가하세요. mDNS는 UDP 5353을 사용하므로 일반 유니캐스트 DNS와는 다른 방식입니다. 53 포트 가로채기만으로 모든 .local 검색 문제가 해결되지는 않습니다.

respect-rules를 켠 뒤 노드 도메인 조회가 시간 초과됨

먼저 proxy-server-nameserver에 연결할 수 있는지, 해당 DNS 서버에 연결하는 과정이 아직 조회되지 않은 프록시에 의존하는지 확인하세요. 필요하면 백업 설정으로 되돌려 노드 도메인을 조회할 독립 경로를 복구한 다음 DNS 아웃바운드 규칙을 단계적으로 강화하세요. 문제가 생겼다고 곧바로 노드 장애로 단정하지 마세요.

테스트 결과가 바뀌지 않음

‘실제 적용된 설정 → DNS 캐시 → 브라우저 DoH → TUN 라우팅 → 규칙 적용’ 순서로 확인하세요. 로그에 이번 테스트 도메인이 전혀 없다면 우선 진입 경로를 확인하고, 조회 기록은 있지만 아웃바운드가 직접 연결이면 규칙을 확인하세요. 아웃바운드가 예상대로인데 지리적 표시만 다르다면 DNS 서버의 애니캐스트와 포워딩 여부를 확인하세요.

  • 공용 테스트 도메인: 새 조회가 커널에 들어오고 DNS 서버 연결에 의도한 아웃바운드가 적용됨
  • 로컬 물리 네트워크 어댑터: 정책에 어긋나는 테스트 도메인의 평문 조회가 발견되지 않음
  • 브라우저와 시스템: 보안 DNS 설정을 각각 테스트하고 한 웹페이지 결과만으로 판단하지 않음
  • LAN 서비스: 라우터, NAS, 프린터가 계속 작동하며 직접 연결할 도메인에는 명확한 예외가 설정됨
  • 설정 유지: 클라이언트를 재시작하고 구독을 업데이트한 뒤 다시 테스트해 오버라이드가 유지되는지 확인

점검 기준은 ‘테스트 페이지에 한 줄만 표시되는 것’이 아닙니다. 각 유형의 DNS 요청에 대해 진입 경로와 DNS 서버, 아웃바운드 경로를 설명할 수 있어야 합니다. 먼저 경로를 확인할 수 있게 만든 뒤 불필요한 예외를 줄이세요. 설정을 쉽게 검토할 수 있을수록 다음 네트워크 변경의 원인을 더 빠르게 찾을 수 있습니다.