이미 노드에 연결은 되지만 도메인 해석이 어느 쪽에서 일어나는지 확실하지 않은 사용자에게 맞는 내용입니다. 읽고 나면 설계상의 직접 해석과 우발적 유출을 구분하고, 접속 로그와 53 포트 필터로 쿼리 경로를 찾아내며, dns 아웃바운드 태그·라우팅 규칙·도메인 스니핑·앱별 프록시 항목을 하나씩 조여 설정할 수 있습니다.
판단 기준: 해석 요청은 어디로 갔는가
DNS 유출의 정확한 정의는 ‘해석이 프록시를 거치지 않았다’가 아니라 ‘해석을 사용할 생각이 없던 리졸버에 맡겼고, 그것도 프록시 터널 밖에서 일어났다’입니다. V2Ray의 동작 방식에서는 도메인을 그대로 원격 노드로 보내 노드 쪽에서 조회를 끝낼 수도 있고, 클라이언트가 먼저 IP로 해석한 뒤 IP로 연결을 맺을 수도 있습니다. 둘 다 정상이며, 차이는 전자는 조회 대상이 노출되지 않고 후자는 조회 내용과 출처가 로컬 네트워크에 남는다는 점입니다.
판단은 한 가지만 보면 됩니다. 이 53 포트 쿼리를 최종적으로 어느 아웃바운드가 처리했는가입니다. 접속 로그에서 아웃바운드 태그가 프록시라면 해석은 노드 쪽에서 일어난 것이고, 태그가 direct라면 로컬에서 일어난 것입니다. 두 번째가 곧 장애는 아닙니다. ‘중국 본토 우회’ 모드에서 중국 본토 도메인을 로컬 DNS로 해석하면 응답이 빠르고 결과도 정확합니다.
실제로 손봐야 하는 것은 세 번째 경우입니다. 도메인이 원래는 원격에서 해석되어야 하는데, 스니핑이 꺼져 있거나 앱별 프록시 설정이 누락됐거나 앱 자체 암호화 DNS를 쓰는 등의 이유로 쿼리가 로컬 리졸버로 들어가는 경우입니다. 이런 유출은 오류를 내지 않고 조용히 일어나므로 로그와 패킷 캡처로 찾아내야 합니다.
위는 정상 경로입니다. 어느 한 고리라도 우회되면 — 앱이 커널을 거치지 않거나, 규칙이 쿼리를 직접 연결로 판정하거나, 커널이 스니핑을 하지 않으면 — 쿼리는 먼저 로컬 리졸버로 떨어지고, 이후 연결이 프록시를 타더라도 되돌릴 수 없습니다.
네 가지 대표 상황과 로그 원문
아래 네 가지는 문제를 찾을 때 가장 자주 보게 되는 로그와 오류로, ‘쿼리가 엉뚱한 방향으로 간’ 흔한 경우를 대부분 커버합니다. 자기 로그와 대조하면 어느 계층에서 문제가 생겼는지 바로 짚을 수 있습니다.
로그: accepted udp:223.5.5.5:53 [socks-in -> direct]
원인과 해결:223.5.5.5는 중국 본토 IP에 속해 ‘중국 본토 우회’ 계열 규칙에서 직접 연결로 매칭되므로 쿼리가 로컬에 남습니다. 중국 본토 도메인이 이 경로를 타는 것은 정상 설계입니다. 모든 쿼리를 노드 쪽에서 내보내고 싶다면 dns 섹션에 별도 태그를 추가하고, 라우팅 규칙으로 그 태그를 프록시 아웃바운드로 보내면 됩니다.
증상: 로그에서 :53 기록이 하나도 검색되지 않음
원인과 해결:쿼리가 애초에 커널로 들어오지 않았습니다. 앱별 프록시에서 해당 앱이 제외됐거나, 브라우저 자체 보안 DNS가 HTTPS 주소로 나간 경우입니다. 먼저 프록시 대상 목록을 확인하고, 브라우저의 보안 DNS를 끈 뒤 다시 재현해 로그에 기록이 남는지 봅니다.
오류: failed to find an available destination
원인과 해결:아웃바운드 주소 해석에서 사용 가능한 결과를 얻지 못한 경우로, DNS 쿼리 자체를 사용할 수 없는 아웃바운드로 보냈을 때 흔합니다. 우선 임시로 로컬 해석으로 되돌려 노드가 살아 있는지 확인하고, 라우팅 규칙에서 dns_inbound 태그가 가리키는 대상과 노드 주소 표기를 점검합니다.
오류: context deadline exceeded
원인과 해결:쿼리가 제한 시간 안에 돌아오지 않은 경우로, 보통 UDP 53이 상위에서 버려지거나 쿼리가 통하지 않는 아웃바운드로 들어갔을 때 생깁니다. 해석 주소를 https로 시작하는 암호화 DNS로 바꿔 다시 재현해 보면 링크 문제인지 규칙 문제인지 구분할 수 있습니다.
이 네 가지 중 직접 연결 아웃바운드가 관련된 항목은 의도한 동작인지 먼저 확인해야 하고, 오류가 관련된 두 항목은 규칙과 해석 주소가 사용 가능한지 점검해야 합니다. ‘설계상의 직접 해석’과 ‘우발적 유출’을 나눠서 봐야 로그의 direct 태그에 휘둘리지 않습니다.
확인 방법: 재현 가능한 세 단계
확인에는 별도 온라인 도구가 필요 없습니다. 클라이언트 자체 로그에 53 포트 필터를 한 번 더하면 해석 경로가 훤히 보입니다. 단계는 v2rayN과 v2rayNG 모두에 적용되며, 데스크톱에서는 패킷 캡처 대조를 한 단계 더합니다.
접속 로그 켜기
v2rayN은 ‘설정’ → ‘매개변수 설정’ → ‘기본 설정’에서 ‘로그 레벨’을 info로 올린 뒤 코어를 재시작하고, v2rayNG는 메인 화면 오른쪽 위 메뉴에서 ‘로그’ 페이지를 엽니다.
해석 한 번 재현하기
시스템 기본 브라우저로 평범한 사이트를 엽니다. 보안 DNS를 켠 브라우저를 쓰면 조회 대상이 HTTPS 주소로 바뀌어 53 포트 필터에 잡히지 않습니다.
53 포트 필터링
로그에서 ‘:53’을 검색해 아웃바운드 태그를 하나씩 확인하고, 데스크톱에서는 동시에 Wireshark로 udp.port == 53을 필터링해 물리 네트워크 카드에 평문 쿼리가 남아 있는지 대조합니다.
프록시 대상 목록 확인
‘앱별 프록시’를 열어 해석을 요청한 앱이 목록에 있는지 확인하고, 안드로이드에서는 시스템 ‘프라이빗 DNS’ 설정값과 브라우저 보안 DNS 사용 여부도 점검합니다.
몇 가지 증거가 서로 맞아떨어져야 합니다. 로그에서 쿼리가 프록시 아웃바운드로 가고, 물리 네트워크 카드에서 평문 53 쿼리가 잡히지 않고, 앱 목록에 누락이 없어야 합니다. 하나만 만족한다면 만족하지 못한 항목을 먼저 해결하고 다시 측정하세요. 해석 주소를 암호화 DNS로 바꾼 뒤 다시 돌려서 로그의 아웃바운드 태그와 패킷 캡처 결과가 동시에 바뀌면 변경이 실제로 적용된 것입니다.
v2rayN: DNS 아웃바운드와 라우팅 규칙
v2rayN의 그래픽 옵션만으로 대부분의 상황을 커버할 수 있지만, DNS 쿼리를 프록시 아웃바운드에 정확히 고정하려면 설정 파일의 dns 섹션에 태그를 추가해야 합니다. 최신 Xray 코어(1.8부터)는 dns 섹션에 tag를 쓸 수 있고, 이 태그는 인바운드 태그로 라우팅 매칭에 참여합니다. 동시에 암호화 해석 주소를 servers 앞에 두면 로컬 해석이 필요할 때도 암호화된 형태로 나갑니다.
{
"dns": {
"tag": "dns_inbound",
"queryStrategy": "UseIPv4",
"servers": [
{ "address": "https://1.1.1.1/dns-query", "domains": ["geosite:geolocation-!cn"] },
{ "address": "223.5.5.5", "domains": ["geosite:cn"] }
]
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{ "type": "field", "inboundTag": ["dns_inbound"], "outboundTag": "proxy" },
{ "type": "field", "domain": ["geosite:cn"], "outboundTag": "direct" }
]
}
}
이 설정은 두 가지를 합니다. 해외 도메인은 암호화 DNS로 해석하고, 중국 본토 도메인은 로컬에서 해석합니다. DNS 쿼리 자체에는 dns_inbound 태그가 붙어 첫 번째 규칙에 의해 프록시 아웃바운드로 들어갑니다. 순서를 바꾸면 안 됩니다. dns_inbound 규칙이 도메인 규칙보다 앞에 있어야 하며, 그렇지 않으면 쿼리가 geosite:cn 같은 규칙에 먼저 걸려 태그가 무용지물이 됩니다.
| 설정 항목 | 위치 | 권장값 | 역할 |
|---|---|---|---|
| 라우팅 모드 | ‘설정’ → ‘매개변수 설정’ → ‘라우팅 설정’ | 중국 본토 우회 | 중국 본토 도메인은 직접 연결, 나머지는 프록시 |
| 도메인 해석 전략 | ‘설정’ → ‘매개변수 설정’ → ‘라우팅 설정’ | IPIfNonMatch | 도메인을 우선 원격에 맡기고, 매칭되지 않으면 IP로 판단 |
| 도메인 스니핑 | ‘설정’ → ‘매개변수 설정’ → ‘라우팅 설정’ | 켜기, 유형은 HTTP와 TLS 선택 | 핸드셰이크에서 도메인을 복원해 IP 기준 오판 방지 |
| DNS 서버 | ‘설정’ → ‘매개변수 설정’ → ‘DNS 설정’ | 암호화 해석 주소 우선 | 로컬 해석이 필요할 때 쿼리를 암호화 형태로 전송 |
| 아웃바운드 도메인 전략 | 설정 파일의 outbound sockopt.domainStrategy | AsIs | 도메인을 그대로 노드로 보내 노드 쪽에서 해석 완료 |
결론: DNS에 먼저 독립된 라우팅을 부여
암호화 DNS는 조회 내용이 노출되는 문제만 해결할 뿐, 쿼리가 어느 아웃바운드로 나가는지는 해결하지 못합니다. 올바른 순서는 dns 태그를 먼저 추가하고 라우팅 규칙으로 dns_inbound를 프록시 아웃바운드에 지정한 다음, 해석 주소를 암호화 형태로 바꾸는 것입니다. 반대로 하면 암호화 쿼리도 그대로 직접 연결 아웃바운드로 나갈 수 있습니다.
v2rayNG 안드로이드: 라우팅 모드, 스니핑, 앱별 프록시
v2rayNG는 Xray 코어를 사용하며, 연결하면 시스템 VpnService가 트래픽을 넘겨받아 앱 연결이 먼저 커널로 들어간 뒤 분기됩니다. 안드로이드에서 유출 지점은 세 곳에 집중됩니다. 앱별 프록시 목록, 도메인 스니핑 스위치, 시스템 프라이빗 DNS입니다. 아래는 v2rayNG 기준이며, v2flyNG는 설정 항목 이름이 비슷하니 대조해 찾으면 됩니다.
- 라우팅 모드: ‘설정’ → ‘라우팅 모드’에서 ‘중국 본토 우회’를 고르면 중국 본토 도메인은 로컬에서 해석되며, 이는 설계된 동작입니다. 모든 도메인을 노드 쪽에서 해석하게 하려면 ‘전역’으로 바꾸세요.
- 도메인 해석 전략: ‘설정’ → ‘도메인 해석 전략’에서 AsIs를 유지하면 도메인이 그대로 노드로 전달됩니다. IP 기준 분기가 필요할 때만 IPIfNonMatch를 선택하세요.
- 도메인 스니핑: ‘설정’에서 ‘도메인 스니핑’을 켜고 HTTP와 TLS를 체크하면 커널이 핸드셰이크에서 도메인을 복원해, 직접 연결 규칙이 IP로 잘못 통과시키는 일을 막습니다.
- 앱별 프록시: ‘설정’ → ‘앱별 프록시’에서 해석을 요청하는 앱이 목록에 있는지 확인하세요. 제외된 앱은 DNS조차 커널로 들어가지 않습니다.
- 프라이빗 DNS: 안드로이드 ‘설정’ → ‘네트워크 및 인터넷’ → ‘프라이빗 DNS’에서 ‘자동’으로 두거나 호스트 이름을 입력하면 해석이 DoT로 나가며, 커널이 가로채는지는 라우팅 규칙에 달려 있습니다.
놓치기 쉬운 지점이 하나 더 있습니다. 일부 브라우저와 앱은 자체 보안 DNS를 내장해 조회 대상이 53 포트가 아닌 리졸버의 HTTPS 주소가 되므로, 로그에서 ‘:53’을 검색해도 전혀 나오지 않습니다. 해결 방법은 리졸버 도메인을 프록시 규칙에 넣거나, 브라우저 설정에서 보안 DNS를 꺼서 해석이 커널의 dns 섹션으로 돌아오게 하는 것입니다.
결론: 안드로이드는 목록을 먼저, 스니핑을 다음에
앱별 프록시가 누락되면 앱 전체가 그 DNS까지 통째로 커널을 우회하므로 영향 범위가 스니핑 스위치보다 훨씬 큽니다. 점검 순서는 목록, 스니핑, 프라이빗 DNS, 그리고 마지막에 설정 파일의 dns 섹션을 권합니다.
자주 나오는 질문
스니핑을 끄면 라우팅이 여전히 IP 기준으로 동작하는데, 실제로 어떤 영향이 있나요?
도메인이 먼저 로컬에서 IP로 해석되고 연결은 IP로 맺어지므로, 직접 연결과 프록시 규칙이 IP로만 판단됩니다. 중국 본토 CDN 도메인이 프록시로 잘못 들어가기 쉽고, 해석 요청도 로컬 네트워크에 남습니다. 스니핑을 켜면 두 문제를 함께 해결할 수 있습니다.
‘중국 본토 우회’ 모드에서 중국 본토 도메인을 로컬 DNS로 해석하는 것은 유출인가요?
아닙니다. 설계상의 직접 해석이며, 조회 대상은 사용자가 직접 고른 로컬 리졸버입니다. 중국 본토 도메인도 노드 쪽에서 해석하게 하려면 라우팅 모드를 ‘전역’으로 바꾸고, 그에 따른 해석 지연 변화를 감수하면 됩니다.
검사 결과에 표시된 리졸버가 제가 입력한 DNS가 아닌데, 왜 그런가요?
먼저 브라우저에서 보안 DNS를 켰는지, 다음으로 시스템에 프라이빗 DNS를 설정했는지 확인하세요. 이 두 곳은 애플리케이션 계층에서 해석을 다른 리졸버로 넘기므로 클라이언트 설정으로는 제어할 수 없습니다. 하나씩 끄고 다시 측정하세요.
구독 업데이트가 계속 시간 초과되는데, DNS와 관련이 있나요?
관련이 있습니다. 구독 도메인 해석이 기본적으로 직접 연결로 나갈 수 있고, 직접 연결 해석이 오염되거나 시간 초과되면 업데이트가 실패합니다. 구독 설정에서 ‘프록시를 통해 구독 업데이트’를 체크해 요청과 해석 모두 노드 쪽에서 나가게 하세요.
암호화 DNS 주소를 입력했는데 적용되지 않나요?
먼저 코어 버전이 해당 표기법을 지원하는지 확인하고, dns 섹션의 tag가 라우팅 규칙에서 참조되는지 점검하세요. 설정을 바꾼 뒤에는 코어를 재시작해야 합니다. 로그에서 DNS 쿼리의 아웃바운드 태그가 바뀌어야 적용된 것입니다.
DNS를 여느 트래픽처럼 관리하면 생각이 정리됩니다. 어느 아웃바운드에서 처리되는지 보고, 독립된 태그와 규칙을 부여한 다음, 어떤 도메인을 로컬 해석으로 남길지 정하면 됩니다. v2rayNG와 v2rayN의 그래픽 옵션이 대부분의 상황을 커버하고, 남은 정밀도는 설정 파일의 dns와 routing 두 섹션이 담당합니다.