V2Ray DNS 누수 점검 방법과 dns 모듈 누수 방지 설정 실전

DNS 누수가 발생하는 이유와 재현 가능한 점검 절차를 설명하고, dns 아웃바운드와 domainStrategy 등 실제 설정으로 DNS 조회 트래픽을 프록시 경로에 연결합니다.

이 글 한눈에 보기

이 글은 v2rayN 또는 Xray로 정상 연결할 수 있지만 점검 페이지에 여전히 현지 통신사 DNS가 표시되는 사용자를 위한 내용입니다. 트래픽 경로, 기준선 점검, Xray 설정, 문제 원인 분석 순서로 설명하며, 완료 후 시스템 DNS, 브라우저 암호화 DNS, 프록시 코어의 DNS 조회를 구분하고 포트 53 조회가 실제로 프록시 아웃바운드로 전달되는지 확인할 수 있습니다.

DNS 누수는 어느 구간에서 발생할까

도메인에 접속할 때 애플리케이션은 보통 먼저 시스템 리졸버에 도메인 조회를 요청한 뒤, 확인된 IP에 연결합니다. 시스템 프록시는 프록시 설정을 지원하는 HTTP 또는 SOCKS 연결만 처리하며, 운영체제가 UDP 53이나 TCP 53으로 보내는 DNS 조회를 자동으로 바꾸지는 않습니다. 따라서 웹 트래픽이 VMess 또는 VLESS 노드를 통해 전달되더라도 도메인 조회는 네트워크 어댑터에 설정된 통신사 리졸버로 직접 전송될 수 있습니다.

누수가 발생했다고 해서 노드가 작동하지 않는 것은 아닙니다. 정확히는 서비스 연결은 프록시를 통과하지만 DNS 조회 요청은 예상과 다른 경로로 전달되는 상태입니다. 점검 페이지에 로컬 네트워크 사업자, 라우터 주소 또는 기업 내부 리졸버가 표시될 때 시스템 설정과 함께 판단해야 합니다. 공용 DNS 이름이 결과에 나타난다는 사실만으로 조회가 프록시를 거쳤다고 단정할 수도 없습니다. 같은 공용 리졸버에 직접 연결할 수도 있고 원격 노드를 통해 접속할 수도 있기 때문입니다.

애플리케이션의 도메인 조회시스템 리졸버로컬 포트 53DNS 아웃바운드프록시 노드 전달원격 리졸버

Xray 설정의 최상위 dns 모듈은 코어 자체의 도메인 조회와 매칭에 필요한 작업을 담당합니다. 예를 들어 노드 서버 도메인을 조회하거나 라우팅 규칙에 필요한 대상 IP를 가져옵니다. 설정 파일에 존재한다는 이유만으로 운영체제의 모든 DNS 조회를 가로채지는 않습니다. 애플리케이션이 시스템에 요청하는 DNS를 처리하려면 수신 포트, 시스템 DNS 대상, 해당 아웃바운드가 모두 올바르게 구성되어야 합니다.

브라우저에 내장된 암호화 DNS는 별도의 경로를 사용합니다. 일반적으로 HTTPS 연결로 DNS 서비스에 접속하므로 로컬 포트 53을 거치지 않습니다. 브라우저 트래픽이 시스템 프록시의 적용을 받으면 이 연결도 프록시를 통과할 수 있지만, 애플리케이션이 시스템 프록시를 우회하면 직접 외부로 나갈 수도 있습니다. 따라서 문제를 점검할 때는 먼저 브라우저의 보안 DNS를 잠시 끄고 시스템 DNS 경로를 확인한 다음, 마지막에 브라우저 설정을 다시 활성화해 별도로 검증해야 합니다.

결론: 먼저 DNS 조회 경로를 구분한 뒤 설정을 변경하세요

낯선 DNS 주소가 보였다고 즉시 노드를 바꾸지 마세요. 먼저 조회가 시스템 포트 53, 브라우저 암호화 DNS, Xray 코어 중 어디에서 발생했는지 확인해야 합니다. 세 경로는 수정해야 할 위치가 서로 다르므로 한꺼번에 테스트하면 결과가 서로 모순될 수 있습니다.

재현 가능한 DNS 누수 점검 기준선 만들기

한 번의 점검 결과는 캐시, 브라우저 프리페치, 리졸버의 애니캐스트 노드에 영향을 받을 수 있습니다. 더 정확하게 확인하려면 같은 네트워크, 같은 노드, 같은 브라우저 설정에서 두 차례 테스트하세요. 1차에서는 DNS를 가로채지 않은 상태의 결과를 기록하고, 2차에서는 설정을 적용한 뒤 캐시를 비운 다음 다시 점검합니다. 각 라운드마다 최소 세 번 무작위 도메인을 조회해 오래된 캐시 때문에 실제 조회가 생략되지 않도록 하세요.

  1. 네트워크 어댑터 DNS 기록

    PowerShell을 열고 Get-DnsClientServerAddress -AddressFamily IPv4를 실행합니다. 현재 사용하는 네트워크 어댑터 이름과 ServerAddresses를 기록하세요. 가정용 네트워크에서는 라우터 주소가 자주 표시되고, 공용 네트워크에서는 리졸버 주소 두 개가 직접 할당될 수도 있습니다.

  2. 점검에 영향을 주는 요소 끄기

    브라우저 보안 DNS를 잠시 끄고 네트워크 스택을 변경하는 다른 프로그램을 종료합니다. 그런 다음 ipconfig /flushdns를 실행해 Windows DNS 캐시를 지우고, 열려 있는 점검 페이지도 닫습니다.

  3. 직접 연결 결과 기록

    v2rayN 시스템 프록시를 끊고 DNS 점검 페이지에 다시 접속해 연속으로 두 번 테스트합니다. 리졸버 수, 네트워크 소속, 지역을 기록하세요. 이 데이터가 로컬 경로의 기준선이며, 페이지에 표시된 국가나 지역명만 저장해서는 안 됩니다.

  4. 연결 후 재점검

    대상 노드에 연결한 뒤 v2rayN의 로컬 SOCKS 포트 10808과 HTTP 포트 10809이 수신 대기 중인지 확인하고, 캐시를 다시 지운 후 테스트합니다. 결과가 직접 연결 기준선과 완전히 같다면 시스템 DNS가 가로채지지 않았을 가능성이 큽니다.

  5. 지정한 수신 포트 검증

    로컬 DNS 수신 포트를 설정한 후 nslookup example.com 127.0.0.1을 실행합니다. 주소가 반환되고 Xray 로그에 dns-indns-out이 나타나야 조회가 예정된 경로로 들어갔다고 볼 수 있습니다.

53
시스템 DNS 표준 포트
10808
예시 SOCKS 포트
10809
예시 HTTP 포트
3회
권장 반복 점검 횟수

예시 환경은 Windows 11 24H2, v2rayN 7.12.5, Xray-core 25.6.8을 사용했습니다. 최초 직접 연결 테스트에서는 로컬 네트워크의 DNS 엔드포인트 3개가 표시되었고 평균 조회 시간은 약 18ms였습니다. 지정한 리졸버에 원격 노드로 접속하도록 변경한 뒤에는 선택한 공용 DNS 서비스만 표시되었으며, 연속 조회 평균은 약 136ms였습니다. 지연 증가는 노드 간 전달에 따른 정상적인 비용이며 실제 수치는 경로 거리에 따라 달라지므로 136ms를 고정 기준으로 삼아서는 안 됩니다.

dns 수신 포트와 아웃바운드로 프록시 경로 연결하기

아래 설정 예시는 로컬 127.0.0.1:53을 DNS 수신 포트로 사용하고, TCP 및 UDP 조회를 dns-out이라는 태그의 아웃바운드로 전달한 다음 기존 proxy 아웃바운드를 통해 전송합니다. 적용하기 전에 현재 유효한 설정에서 선택한 노드의 아웃바운드 태그를 확인하세요. 실제 태그가 proxy가 아니라면 proxySettings.tag를 현재 태그로 변경해야 합니다.

포트 53은 시스템 서비스, 가상 네트워크 어댑터 프로그램 또는 로컬 DNS 소프트웨어가 이미 사용 중일 수 있으며, 낮은 포트에서 수신 대기하려면 보통 관리자 권한이 필요합니다. 먼저 수신 포트를 1053으로 바꿔 Xray 설정이 시작되는지 확인할 수 있지만 Windows 네트워크 어댑터의 DNS 설정에는 비표준 포트를 직접 입력할 수 없습니다. 시스템 조회를 정식으로 가로채려면 포트 53을 비우고 활성 네트워크 어댑터의 IPv4 DNS를 127.0.0.1로 지정해야 합니다.

{
  "dns": {
    "servers": [
      {
        "address": "1.1.1.1",
        "domains": [
          "geosite:geolocation-!cn"
        ]
      },
      {
        "address": "223.5.5.5",
        "domains": [
          "geosite:cn"
        ]
      }
    ],
    "queryStrategy": "UseIPv4",
    "disableCache": false
  },
  "inbounds": [
    {
      "tag": "dns-in",
      "listen": "127.0.0.1",
      "port": 53,
      "protocol": "dokodemo-door",
      "settings": {
        "address": "1.1.1.1",
        "port": 53,
        "network": "tcp,udp"
      }
    }
  ],
  "outbounds": [
    {
      "tag": "dns-out",
      "protocol": "dns",
      "settings": {
        "address": "1.1.1.1",
        "port": 53,
        "network": "tcp",
        "nonIPQuery": "drop"
      },
      "proxySettings": {
        "tag": "proxy"
      }
    }
  ],
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "inboundTag": [
          "dns-in"
        ],
        "outboundTag": "dns-out"
      }
    ]
  }
}

queryStrategy: UseIPv4는 내장 DNS가 IPv4 결과를 우선 반환하도록 합니다. 현재 노드나 로컬 네트워크에서 안정적인 IPv6 아웃바운드를 지원하지 않을 때 적합합니다. 경로가 IPv6를 완전히 지원한다면 실제 대상에 따라 UseIP로 변경할 수 있지만, 프록시 노드, 시스템 라우팅, 원격 리졸버를 함께 점검해야 합니다. AAAA 레코드만 얻고 사용할 수 있는 IPv6 아웃바운드는 없는 상황을 피하기 위해서입니다.

nonIPQuery: drop은 DNS 아웃바운드에서 A 및 AAAA가 아닌 유형의 조회를 버립니다. 일반 웹사이트 조회만 필요한 단순한 환경에는 적합하지만 TXT, SRV 등의 레코드에 의존하는 기업 서비스에 영향을 줄 수 있습니다. 메일 인증, 서비스 검색 또는 내부 애플리케이션 조회에 문제가 생기면 이 항목을 제거하고 다시 테스트하세요. 문제를 VMess 또는 VLESS 프로토콜 탓으로 돌려서는 안 됩니다.

결론: 수신 포트, 라우팅, 시스템 DNS 지정이 모두 필요합니다

최상위 dns 설정만 있으면 시스템 조회가 직접 연결될 수 있고, 로컬 수신 포트만 만들어도 네트워크 어댑터 DNS가 127.0.0.1을 가리키지 않으면 실제 요청을 받지 못합니다. DNS 가로채기가 완료되었는지는 포트 수신 대기, 로그 매칭, 재점검 결과가 모두 충족되는지로 판단해야 합니다.

domainStrategy는 DNS 누수 차단 스위치가 아닙니다

routing.domainStrategy는 라우팅 모듈이 규칙을 매칭할 때 대상 도메인을 IP로 조회할지 결정합니다. 이는 ‘라우팅 규칙에서 추가 조회가 필요한가’를 처리하는 설정이지, ‘운영체제 DNS를 어디로 보낼 것인가’를 정하는 설정이 아닙니다. AsIsIPIfNonMatch로 바꾸면 IP 규칙이 매칭될 기회가 생길 수 있지만, 네트워크 어댑터가 보내는 UDP 53 요청을 자동으로 차단하지는 않습니다.

조회 동작 적용 기준
AsIs 원래 도메인으로 도메인 규칙을 적용하며 IP 규칙을 위해 능동적으로 조회하지 않음 규칙이 주로 domain과 geosite로 구성되어 추가 조회를 줄임
IPIfNonMatch 도메인 규칙이 매칭되지 않으면 대상을 조회한 뒤 IP 규칙을 시도함 geosite와 geoip를 함께 사용해 매칭 범위와 조회량의 균형을 맞춤
IPOnDemand 대상 IP가 필요할 수 있는 규칙을 만나면 미리 조회함 IP 규칙이 우선이고 조기 조회가 실제로 필요한 설정

일반적으로 IPIfNonMatch를 선택합니다. 도메인 규칙을 먼저 적용하고, 매칭되지 않을 때 geoip 또는 명시적인 IP 규칙을 위해 조회합니다. 이렇게 하면 모든 요청이 미리 조회되는 것을 막으면서 IP 분기 기능을 유지할 수 있습니다. 라우팅 목록에서 IP 규칙이 매우 앞에 있다면 IPOnDemand가 코어의 DNS 조회 수를 크게 늘릴 수 있으므로 이름만 보고 선택하지 말고 로그를 함께 확인하세요.

최상위 dns.servers의 도메인별 DNS 분기와 routing.rules는 서로 다른 로직입니다. 전자는 특정 도메인을 어느 리졸버에 맡길지 결정하고, 후자는 연결을 direct, proxy, block 중 어디로 보낼지 결정합니다. geosite:cn을 가까운 리졸버에서 조회하면서 모든 DNS 조회는 원격 노드를 통해 전달하려 한다면 두 목표가 충돌하지 않는지 명확히 확인해야 합니다. 리졸버 주소와 전송 경로는 별도로 설계해야 합니다.

v2rayN에서 설정 적용 후 덮어쓰기 방지하기

v2rayN의 일반 구독 노드는 클라이언트가 실행 설정을 생성하므로 임시 JSON 파일을 직접 수정하면 서버 전환, 구독 업데이트 또는 코어 재시작 후 덮어써질 수 있습니다. DNS 수신 포트와 아웃바운드를 완전히 제어해야 한다면 사용자 지정 설정 서버를 사용하고, 기존 노드 매개변수와 라우팅 규칙, 위 DNS 구조를 하나의 유효한 설정으로 병합하세요.

  1. 코어 유형 확인

    「설정」→「매개변수 설정」→「Core 유형」으로 이동해 현재 서버가 Xray 코어를 사용하는지 확인합니다. 저장 후 코어를 다시 시작해 다른 코어가 설정 문법을 해석하는 일을 방지하세요.

  2. 아웃바운드 태그 확인

    현재 실행 중인 설정을 열고 선택한 노드에 해당하는 outbounds.tag를 찾습니다. 이 글의 예시는 proxy를 사용하지만 실제 파일의 이름이 다르면 DNS 아웃바운드의 프록시 태그도 동일하게 맞춰야 합니다.

  3. 사용자 지정 설정 추가

    「서버」→「사용자 지정 설정 서버 추가」에서 준비한 JSON 파일을 선택합니다. 먼저 로컬 DNS 수신 포트를 1053으로 유지한 상태에서 시작 테스트를 진행하고, 문법과 라우팅 로그가 정상인지 확인하세요.

  4. 포트 53 비우기

    Get-NetUDPEndpoint -LocalPort 53Get-NetTCPConnection -LocalPort 53을 실행해 사용 중인 프로세스를 확인합니다. 충돌을 해결한 뒤 설정 포트를 53으로 되돌리고 관리자 권한으로 v2rayN을 다시 시작하세요.

  5. 활성 네트워크 어댑터 변경

    현재 활성 네트워크 어댑터의 IPv4 DNS 서버를 127.0.0.1로 설정합니다. 로컬 통신사 DNS를 보조 항목으로 동시에 남겨 두지 마세요. 로컬 서비스가 일시적으로 응답하지 않으면 시스템이 보조 리졸버로 자동 전환할 수 있습니다.

  6. 캐시를 지운 뒤 검증

    ipconfig /flushdns를 실행하고 nslookup example.com 127.0.0.1로 수신 포트를 검증한 다음 세 차례 점검합니다. 완료 후 로그에서 dns-indns-out으로 전달되었는지 확인하세요.

시스템 프록시만 사용하고 TUN을 사용하지 않으면 시스템 프록시 설정을 따르지 않는 애플리케이션 연결은 직접 연결될 수 있습니다. DNS 가로채기는 조회 경로만 해결할 뿐 모든 트래픽을 가로채지는 않습니다. TUN을 사용할 때도 DNS 하이재킹과 라우팅 규칙을 확인해야 합니다. 기존 UDP 및 TCP 53 트래픽은 캡처할 수 있지만 애플리케이션이 직접 만드는 HTTPS DNS 연결은 일반 443 트래픽으로 보이므로 해당 애플리케이션의 트래픽 규칙이 경로를 결정합니다.

자주 발생하는 오류와 점검 순서

문제 해결 시 먼저 코어가 시작되었는지 확인하고, 다음으로 포트가 수신 대기 중인지 확인한 뒤 점검 페이지를 살펴보세요. 점검 페이지는 경로의 마지막에 있으므로 앞의 두 항목이 실패한 상태에서 반복 새로고침해도 더 많은 정보를 얻을 수 없습니다. 로그 수준은 일시적으로 info로 설정하고, 원인 파악 후에는 평소 설정으로 되돌려 불필요한 접속 기록이 장기간 쌓이지 않도록 하세요.

오류: failed to listen TCP on 127.0.0.1:53

원인 및 해결 방법: 포트 53을 다른 프로세스가 사용 중이거나 현재 프로세스에 충분한 권한이 없습니다. 먼저 PowerShell로 TCP 및 UDP 엔드포인트를 조회하고 충돌하는 서비스를 종료한 다음 관리자 권한으로 코어를 다시 시작하세요.

오류: failed to find an available destination

원인 및 해결 방법: 노드 서버 도메인 또는 DNS 대상의 부트스트랩 조회가 완료되지 않았습니다. 서버 주소 철자를 확인하고 임시로 직접 연결 가능한 부트스트랩 리졸버를 제공한 뒤, 노드 연결이 완료되면 대상 경로를 복원하세요.

오류: outbound proxy not found

원인 및 해결 방법:proxySettings.tag가 존재하지 않는 아웃바운드 태그를 참조하고 있습니다. 실제 실행 설정을 열어 선택한 노드의 정확한 tag를 복사한 다음 DNS 아웃바운드 참조도 함께 수정하세요.

현상: nslookup은 시간 초과되지만 코어에는 오류가 없음

원인 및 해결 방법: 네트워크 어댑터가 127.0.0.1을 가리키지 않거나 방화벽이 로컬 UDP 53을 차단하고 있을 수 있습니다. 먼저 nslookup example.com 127.0.0.1을 명시적으로 실행한 뒤 네트워크 어댑터 설정과 로컬 규칙을 각각 확인하세요.

현상: 점검 결과에 여전히 두 개의 DNS 서비스가 표시됨

원인 및 해결 방법: 브라우저 보안 DNS, IPv6 DNS 또는 보조 네트워크 어댑터가 별도로 조회하고 있을 수 있습니다. 브라우저 암호화 DNS를 항목별로 끄고 IPv6 DNS 주소를 확인한 다음 사용하지 않는 가상 네트워크 어댑터를 비활성화하고 다시 점검하세요.

로그에 요청이 dns-in에는 매칭되지만 dns-out으로 전달되지 않는다면 라우팅 규칙 순서를 확인해야 합니다. Xray 라우팅은 위에서 아래로 매칭되므로 앞쪽의 일반적인 수신 규칙이 요청을 먼저 direct로 보낼 수 있습니다. dns-in 대상 규칙을 일반 규칙보다 앞에 배치하고 중복 tag가 없는지 확인하세요.

Xray 로그가 정상이고 시스템 조회도 문제없지만 브라우저 점검 결과만 다르다면, 대개 브라우저가 독립적인 DNS 경로를 사용한다는 뜻입니다. 보안 DNS를 다시 활성화한 뒤에는 일반 HTTPS 트래픽으로 간주해 점검하세요. 포트 53 설정을 계속 바꾸기보다 브라우저 프로세스가 시스템 프록시 또는 TUN을 사용하는지 확인해야 합니다.

0.0.0.0:53
의도치 않은 LAN 노출 방지
127.0.0.1:53
권장 로컬 수신 주소
1053
시작 단계 테스트 포트

수신 주소는 127.0.0.1로 유지하고 편의를 위해 0.0.0.0으로 바꾸지 않는 것이 좋습니다. 후자는 모든 네트워크 어댑터에서 수신하게 하므로 LAN 장치가 해당 포트에 접근할 수 있고 방화벽 설정 범위도 넓어집니다. 다른 장치에 DNS 서비스를 제공해야 하는 명확한 이유가 있을 때만 LAN 주소에 바인딩하고 접근 제어를 설정하세요.

최종 판단: 네 가지 결과로 전체 경로 확인

네트워크 어댑터 DNS가 127.0.0.1을 가리키고, 로컬 포트 53이 정상적으로 수신 대기하며, 로그에 dns-in에서 dns-out으로 전달된 기록이 있고, 점검 결과에 직접 연결 기준선의 리졸버가 더 이상 나타나지 않아야 시스템 DNS가 예정된 프록시 경로에 들어갔다고 확인할 수 있습니다.

v2rayN 다운로드