1. DNS 출구, 웹 트래픽 출구, 규칙의 기대 동작 구분하기

웹페이지에 프록시 IP가 표시된다고 해서 도메인 조회도 프록시를 거쳤다는 뜻은 아닙니다. 한 번 접속할 때 적어도 두 경로가 사용됩니다. 먼저 앱이 도메인을 조회하고, 이어서 대상 주소로 연결합니다. 시스템 프록시는 프록시 설정을 따르는 앱의 트래픽만 처리하는 경우가 많습니다. 시스템 리졸버, 앱 자체 DNS, 브라우저 보안 DNS는 서로 다른 경로를 사용할 수 있습니다.

이 글에서 “DNS 누수”란 지정된 경로로 처리되어야 할 조회가 예상하지 못한 리졸버로 전달되거나 로컬 네트워크를 통해 직접 전송되는 경우를 뜻합니다. 규칙상 로컬 도메인을 직접 연결하고 로컬 리졸버를 사용하는 것이 맞다면, 로컬 리졸버가 감지되어도 반드시 문제는 아닙니다. 반면 일반 조회를 모두 프록시로 전달하려는 설정이라면 같은 결과를 점검해 볼 필요가 있습니다.

확인 항목알 수 있는 내용이것만으로는 알 수 없는 내용
웹페이지의 공인 IP해당 웹페이지 요청의 출구다른 앱이나 DNS도 같은 출구를 사용하는지 여부
테스트 사이트에 표시된 DNS IP재귀 조회에 사용된 서버의 출구기기와 리졸버 사이의 트래픽이 프록시를 통과했는지 여부
198.18.x.x 반환이번 조회에서 일반적으로 fake-ip에 사용하는 주소 대역의 매핑을 받음모든 시스템 조회가 가로채졌는지 여부
통신사 로컬 리졸버가 표시됨확인이 필요한 로컬 DNS 경로가 있음모든 연결이 프록시를 우회하는지 여부

2. 국가명만 보지 말고 테스트 사이트에서 세 가지를 비교하기

먼저 테스트 조건을 기록하세요

dnsleaktest.com의 Standard test와 Extended test, 그리고 browserleaks.com/dns를 함께 확인할 수 있습니다. 테스트 도메인 조회를 유도한 뒤 권한 서버에 도달한 조회의 재귀 리졸버 출구를 기록하는 방식입니다. 브라우저에서 운영체제의 DNS 설정을 직접 읽어 오는 것은 아닙니다.

  1. 가정용 Wi-Fi처럼 현재 네트워크를 기록하고, 클라이언트 모드, 선택한 노드, TUN 사용 여부, 브라우저 보안 DNS 상태도 적어 둡니다.
  2. 프록시를 끄고 한 번 테스트해 기준값을 확보하세요. 공인 IP, DNS 서비스 제공업체, 리졸버 주소를 기록하되 전체 화면을 공개할 필요는 없습니다.
  3. 노드는 그대로 둔 채 프록시를 켜고 다시 테스트하세요. 시스템 프록시 모드와 TUN 모드는 각각 따로 기록해 한 번에 여러 조건을 바꾸지 않도록 합니다.
  4. 브라우저 보안 DNS를 잠시 끄고 브라우저를 다시 시작한 뒤 재검사하세요. 결과가 달라지면 우선 브라우저 자체 DoH 경로를 확인합니다.

위 내용은 권장 절차이며 이 사이트가 직접 측정한 결과가 아닙니다. 전후 결과가 달라졌는지, 설정한 정책에 부합하는지를 중심으로 비교하세요. 특정 국가 표시만으로 판단해서는 안 됩니다. 공용 DNS는 애니캐스트 네트워크를 사용하고 지리 정보 데이터베이스도 갱신이 늦을 수 있어, 리졸버 등록 위치와 실제 서비스 노드 위치가 다를 수 있습니다.

결과에 따라 점검 범위 좁히기

  • 웹 IP는 바뀌었지만 DNS는 가정용 인터넷 통신사로 표시됨: 시스템 DNS가 코어로 전달되는지, 브라우저에 별도 DNS 설정이 있는지 먼저 확인합니다.
  • 특정 브라우저에서만 DNS가 다르게 표시됨: 해당 브라우저의 보안 DNS, 확장 프로그램, 독립 프록시 설정을 먼저 확인합니다.
  • 공용 DNS 업체 두 곳이 표시됨: 업스트림이나 대체 리졸버를 여러 개 설정했을 수 있습니다. 표시된 개수만으로 누수라고 단정할 수 없습니다.
  • TUN을 켠 뒤에야 결과가 예상과 일치함: 시스템 프록시가 기존 조회 경로를 처리하지 못했다는 뜻일 수 있습니다. 적용되는 앱 범위와 IPv6도 확인하세요.

3. fake-ip로 도메인 매핑을 만들고 업스트림 리졸버 확인하기

fake-ip는 앱에 가상 주소를 반환하고 코어에 도메인 매핑을 저장합니다. 이후 연결이 코어에 도달하면 이 매핑을 바탕으로 도메인 규칙을 적용할 수 있습니다. 암호화 프로토콜이 아니며 운영체제 DNS를 자동으로 가로채지도 않습니다. 설정을 켰더라도 시스템이 계속 라우터에 조회를 보내면 이 경로를 우회할 수 있습니다.

아래는 기존 설정에 병합할 DNS 예시이며 완성된 구독 설정이 아닙니다. 기존 노드, 프록시 그룹, 규칙은 유지하세요. 기존 최상위 dns: 항목을 먼저 전체적으로 확인한 뒤 수정하고, 같은 파일에 동일한 이름의 항목을 두 번 추가하지 마세요.

config.yaml · DNS 설정 예시
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:
    - 223.5.5.5
  nameserver:
    - https://cloudflare-dns.com/dns-query
  • listen은 코어의 DNS 수신 주소입니다. 예시의 1053은 우선 특정 경로를 테스트하기 위한 포트이며, 시스템이 이 포트를 자동으로 사용하게 하지는 않습니다.
  • default-nameserver는 DNS 서버 자체의 도메인을 조회하는 데 사용됩니다. 조회 시작 경로의 일부이지 일반 조회에 사용하는 기본 업스트림 목록은 아닙니다.
  • proxy-server-nameserver는 프록시 노드 도메인을 조회합니다. 노드를 조회하려면 먼저 프록시에 연결해야 하고, 프록시에 연결하려면 먼저 노드를 조회해야 하는 순환 의존성을 방지합니다.
  • nameserver의 DoH 주소는 일반 업스트림 조회에 사용됩니다. HTTPS는 리졸버까지의 전송을 암호화하지만, 그 연결이 반드시 프록시를 통과한다는 뜻은 아닙니다.
  • fake-ip-filter에 등록된 도메인에는 fake-ip 매핑이 적용되지 않습니다. 이 목록은 직접 연결 규칙과 같지 않으며 해당 도메인의 DNS 조회가 사라지는 것도 아닙니다.

4. respect-rules는 업스트림 연결 경로를 정하며 시스템 DNS를 가로채지는 않습니다

respect-rules: true를 설정하면 관련 DNS 업스트림 연결에 라우팅 규칙이 적용됩니다. 이는 “코어가 업스트림에 요청할 때 어떤 출구를 사용할지”를 정하는 설정이지, “시스템의 요청이 코어에 들어오는지”를 정하는 설정은 아닙니다. 두 경로를 따로 확인하면 문제 해결 과정이 훨씬 간단해집니다.

최종적으로 적용되는 규칙 확인하기

  1. 현재 규칙 모드를 사용 중인지, 즉 mode: rule인지 확인하세요. 전역 모드나 직접 연결 모드의 동작으로 규칙 모드의 결과를 대신 판단할 수 없습니다.
  2. DNS 서비스 도메인이 앞쪽 규칙이나 규칙 세트에서 DIRECT로 처리되는지 확인하세요. 직접 연결 규칙이 적용되면 respect-rules를 켜도 프록시로 바뀌지 않습니다.
  3. 클라이언트의 연결 패널과 로그에서 업스트림 연결에 적용된 규칙과 출구를 확인하세요. 필요하면 잠시 로그 수준을 높이고, 점검이 끝나면 원래대로 되돌려 도메인이 과도하게 기록되지 않도록 합니다.
  4. DNS 서비스 도메인에 별도 출구를 지정하려면 기존 프록시 그룹의 정확한 이름을 사용하고, 먼저 적용될 수 있는 광범위한 규칙보다 앞에 배치하세요. 설정에 실제로 없는 그룹 이름을 복사해 쓰지 마세요.

기존 설정에 nameserver-policy, direct-nameserver 또는 fallback이 있으면 함께 점검하세요. nameserver만 수정해도 특정 도메인이 실제 사용하는 리졸버는 바뀌지 않을 수 있습니다. 처음 원인을 찾을 때는 변수를 줄이고, 최소 설정이 정상인지 확인한 뒤 정책을 하나씩 복원하는 편이 좋습니다.

fallback은 단순히 “기본 DNS가 시간 초과되면 시작”하는 스위치가 아닙니다. 대체 결과의 선택에는 fallback-filter 등 여러 조건이 적용됩니다. 누수를 고치겠다며 리졸버를 여러 개 무작정 추가하면 테스트 결과만 복잡해질 수 있습니다.

5. 시스템 DNS 가로채기: TUN과 53번 포트의 역할

대부분의 데스크톱 운영체제 네트워크 설정에서는 DNS 서버 주소만 지정할 수 있고 1053 같은 사용자 지정 포트는 입력할 수 없습니다. 따라서 시스템 DNS를 127.0.0.1로 설정하고 코어는 127.0.0.1:1053에서만 수신하게 하면 포트가 맞지 않습니다. 시스템이 로컬 DNS에 직접 연결하는 방식을 쓸 때는 53번 포트에서 수신하도록 하고 권한과 포트 점유 문제를 처리하세요. 수신 주소를 무턱대고 전체 로컬 네트워크에 공개하지 마세요.

또 다른 일반적인 방법은 TUN으로 네트워크 트래픽을 가로채고, TUN으로 들어온 일반 DNS 요청을 코어가 처리하도록 하는 것입니다. 아래 내용도 기존 설정에 병합하는 예시입니다. 클라이언트 UI가 별도의 TUN 설정을 생성하고 있지 않은지 먼저 확인하세요.

config.yaml · TUN 설정 예시
tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53
  • any:53과 tcp://any:53은 TUN으로 들어오는 UDP 및 TCP 53번 포트 DNS 요청을 각각 처리합니다.
  • auto-route는 관련 경로를 자동으로 설정합니다. 시작에 실패하면 DNS 주소를 반복해서 바꾸기보다 서비스 권한, 경로 충돌, 다른 VPN을 먼저 확인하세요.
  • 로컬 링크로 향하거나 라우팅에서 제외된 DNS 요청은 TUN에 들어오지 않을 수 있습니다. 라우터 DNS, 다른 가상 네트워크 어댑터, 로컬 루프백 리졸버는 각각 따로 확인해야 합니다.
  • DoH는 보통 HTTPS의 443번 포트를, DoT는 보통 853번 포트를 사용합니다. 53번 포트 가로채기만으로 이 트래픽이 코어 DNS 조회로 자동 변환되지는 않습니다.

6. Windows, macOS, Linux, Android에서 각각 재검증하기

Windows: 코어 수신 테스트와 시스템 경로 테스트 구분하기

관리자 권한으로 클라이언트에 필요한 서비스나 TUN을 시작한 뒤 아래 두 명령으로 확인합니다. 첫 번째 명령은 로컬 1053번 포트를 지정해 조회하고, 두 번째는 시스템 기본 DNS를 사용합니다. 두 명령은 서로 다른 경로를 검증합니다.

Windows · PowerShell 또는 명령 프롬프트
nslookup -port=1053 example.com 127.0.0.1
nslookup example.com
ipconfig /all
ipconfig /flushdns

첫 번째 명령은 도메인이 필터 목록에 없을 때 보통 설정된 주소 풀의 fake-ip를 반환해야 합니다. 두 번째 명령은 TUN 가로채기가 적용되더라도 UI에 원래 설정된 DNS 서버 이름이 표시될 수 있습니다. 해당 줄만 보고 실패라고 판단하지 마세요. 반환 주소, 로그, 테스트 사이트 결과를 함께 확인하세요. 캐시를 비운 뒤 테스트 도메인에 다시 접속해 이전 응답이 영향을 주지 않도록 합니다.

macOS: Wi-Fi 화면만 보지 말고 시스템 리졸버 목록 확인하기

macOS · 터미널
scutil --dns
dig @127.0.0.1 -p 1053 example.com A
dscacheutil -q host -a name example.com
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

scutil --dns로 인터페이스나 도메인별 리졸버 설정을 확인할 수 있습니다. dig를 지정해 조회하면 코어 수신을 확인할 수 있고, dscacheutil은 시스템 조회 경로를 추가로 살펴보는 데 유용합니다. TUN에 필요한 권한을 부여한 뒤 브라우저에서도 다시 테스트하세요. dig가 성공했다고 시스템 단계 확인을 생략하지 마세요.

Linux: systemd-resolved와 루프백 주소 확인하기

Linux · systemd-resolved 사용 시스템
resolvectl status
resolvectl query example.com
dig @127.0.0.1 -p 1053 example.com A
sudo resolvectl flush-caches

/etc/resolv.conf에 127.0.0.53이 표시되면 보통 앱이 로컬 DNS 스텁에 먼저 접속한다는 뜻이며, 최종 업스트림이 로컬이라는 의미는 아닙니다. resolvectl status에서 인터페이스별 DNS를 이어서 확인하세요. systemd-resolved를 사용하지 않는 배포판에서는 NetworkManager나 실제 DNS 관리 서비스를 점검하고, 서비스가 자동 생성하는 파일을 직접 덮어쓰지 마세요.

Android: 비공개 DNS와 브라우저 보안 DNS를 따로 점검하기

기본 Android에서 흔히 사용하는 ‘설정’ → ‘네트워크 및 인터넷’ → ‘비공개 DNS’ 경로로 이동해 지정된 비공개 DNS를 잠시 끈 뒤 같은 테스트를 다시 실행하세요. 제조사에 따라 메뉴 이름은 다를 수 있습니다. 클라이언트에 VPN 권한이 부여되었는지, 앱별 프록시에서 테스트 브라우저가 제외되지 않았는지도 확인하세요. Android에서는 일반 VPN 서비스를 보통 한 번에 하나만 실행할 수 있으므로 다른 VPN이나 로컬 필터링 도구가 경로를 점유할 수 있습니다.

Chrome 데스크톱 버전에서는 보통 ‘설정’ → ‘개인 정보 보호 및 보안’ → ‘보안’ → ‘보안 DNS 사용’에서 설정을 확인할 수 있습니다. 변수 확인을 위해 잠시 끈 뒤 테스트가 끝나면 다시 켜고 해당 DoH 연결의 실제 출구를 확인하세요. 브라우저 DoH를 유지한다고 해서 반드시 누수인 것은 아닙니다. 중요한 것은 조회 및 라우팅 정책에 부합하는지 여부입니다.

7. fake-ip가 적용됐는데도 문제가 있으면 확인할 네 가지

  1. IPv6가 다른 경로를 사용함: dns.ipv6: false는 코어 DNS의 AAAA 조회 처리를 제어하며 시스템 IPv6를 끄는 설정은 아닙니다. 앱 캐시, 자체 리졸버, 이미 확보된 IPv6 주소로 연결이 계속될 수 있으므로 IPv6 경로와 TUN 적용 범위를 확인하세요.
  2. 구독 업데이트가 수동 변경 사항을 덮어씀: 다시 불러온 뒤 편집기의 파일만 보지 말고 실제 적용 중인 설정을 확인하세요. 계속 유지해야 하는 항목은 클라이언트에서 지원하는 덮어쓰기, 병합 또는 영구 설정 기능으로 관리해야 합니다.
  3. 필터 목록이 너무 큼: 공개 도메인을 대량으로 fake-ip-filter에 추가하면 실제 주소가 반환되지만 DNS 출구가 자동으로 바로잡히지는 않습니다. 호환성 문제가 확인된 도메인만 예외로 추가하고, 추가할 때마다 다시 테스트하세요.
  4. 캐시와 기존 연결이 남아 있음: 시스템 캐시, 브라우저 캐시, 코어 매핑, 이미 수립된 연결은 각각 수명이 다릅니다. 설정을 다시 불러온 뒤 테스트 탭을 닫고, 필요하면 브라우저를 재시작한 다음 새로 검사하세요. 이전 연결을 새 설정의 성적표로 삼지 마세요.

마지막으로 점검표로 설정 검수하기

  • 127.0.0.1:1053을 지정한 조회에 응답이 있고, 일반 테스트 도메인에서 예상한 fake-ip 매핑을 받습니다.
  • 시스템 기본 조회와 실제 브라우저 테스트를 모두 확인했으며 코어 포트만 테스트한 것이 아닙니다.
  • DNS 업스트림 출구가 규칙과 일치하고, 노드 도메인 및 시작 단계 DNS 예외를 명확히 기록했습니다.
  • 일반 DNS, 브라우저 DoH, IPv6, 앱별 제외 항목을 각각 점검했으며 53번 포트 가로채기를 모든 프로토콜의 가로채기로 오해하지 않았습니다.
  • 구독 업데이트, 클라이언트 재시작, Wi-Fi 전환 후에도 다시 테스트해 정해 둔 정책과 결과가 일치합니다.

점검 순서는 세 문장으로 정리할 수 있습니다. 먼저 조회가 코어에 들어오는지 확인하고, 다음으로 업스트림 연결이 올바른 출구를 사용하는지 확인한 뒤, 자주 쓰는 앱이 다른 경로를 사용하지 않는지 확인하세요. fake-ip는 도메인 매핑, respect-rules는 업스트림 경로 선택, 시스템 DNS 가로채기는 요청 진입 경로를 담당합니다. 역할을 분명히 나누면 로그를 보고 추측할 필요가 줄어듭니다.