노드에 연결할 수 있고 DNS 및 라우팅 규칙을 조정하려는 사용자를 위한 글입니다. 예시는 Xray 코어의 기존 JSON 설정을 기준으로 DNS 서버 선택, 응답 주소 필터링, 연결 출구를 구분하고, 적용할 수 있는 설정 조각과 확인 절차를 제공합니다. V2Fly에서 지원하는 필드는 실제 코어 버전을 확인해야 하며, 클라이언트 이름만으로 호환 여부를 판단할 수 없습니다.
DNS 조회와 연결 출구를 구분하세요
DNS 분할은 도메인을 어느 DNS 서버에 조회할지 정하고, 라우팅 분할은 연결을 어느 아웃바운드로 보낼지 정합니다. 서로 연관은 있지만 같은 설정은 아닙니다. 특정 도메인의 DNS 서버를 중국 본토 서버로 지정해도 반드시 직접 연결되는 것은 아닙니다. 연결에 프록시 아웃바운드를 지정해도 앱이 앞서 보낸 DNS 조회까지 프록시를 거친다는 뜻은 아닙니다.
이 흐름은 이 글에서 사용하는 routing.domainStrategy: "IPIfNonMatch"에 해당합니다. 먼저 도메인 규칙을 확인하고, 일치하는 규칙이 없을 때 IP 규칙에 필요한 주소를 조회합니다. 도메인 규칙이 이미 일치하면 라우팅 단계에서 내장 DNS를 전혀 조회하지 않을 수도 있습니다. 이후의 조회 여부는 실제 아웃바운드 처리 방식에 따라 달라집니다. 따라서 DNS 로그가 보이지 않는다는 이유만으로 설정이 적용되지 않았다고 판단해서는 안 됩니다.
- 앱이 도메인을 코어에 전달하는 경우: 도메인 규칙을 바로 적용할 수 있고, 코어가 내장 DNS로 조회할 수도 있습니다.
- 앱이 IP 주소를 코어에 전달하는 경우: 원래 도메인 정보가 이미 사라졌을 수 있으므로
geosite만으로 도메인을 복원할 수 없습니다. - 앱에서 암호화 DNS를 직접 사용하는 경우: 조회가 코어의
dns설정을 우회할 수 있으므로 앱 설정을 별도로 확인해야 합니다. - 시스템 프록시만 켠 경우: 일반적으로 프록시를 지원하는 앱의 연결만 프록시로 보내며, 시스템의 모든 DNS 트래픽을 가로채지는 않습니다.
servers, domains, expectIPs
dns.servers는 DNS 서버 목록으로, 서버 주소나 조건이 포함된 객체를 지정할 수 있습니다. 객체의 domains는 우선 적용할 도메인을 지정하고, expectIPs는 해당 서버가 반환한 주소가 기대한 범위에 속하는지 확인합니다. 전자는 조회할 서버를 선택하고 후자는 응답을 필터링하므로 서로 대체할 수 없습니다.
중국 본토 도메인용 DNS 서버
- address
223.5.5.5- domains
geosite:cn- expectIPs
geoip:cn- skipFallback
true
중국 본토 도메인을 우선 처리하고, 다른 도메인의 일반 폴백 후보에서는 제외합니다.
일반 폴백 DNS 서버
- address
https://1.1.1.1/dns-query- 전송 방식
- HTTPS
- domains
- 제한 없음
- 조회 주소 계열
- 전역
UseIPv4설정 상속
전용 규칙에 일치하지 않거나 전용 서버의 응답이 필터를 통과하지 못한 조회를 처리합니다.
skipFallback: true는 “이 서버를 일반 폴백으로 사용하지 않음”이라는 뜻이지, “이 서버에 일치한 뒤에는 폴백을 금지함”이라는 뜻이 아닙니다. 중국 본토 도메인의 응답이 expectIPs 조건에 맞지 않으면 예시 설정은 다른 폴백 DNS 서버를 시도할 수 있습니다. 두 의미를 혼동하면 실제 조회가 어디로 전달되는지 잘못 판단할 수 있습니다.
geosite:cn은 도메인 분류 데이터에서, geoip:cn은 IP 분류 데이터에서 가져옵니다. 실시간 위치 정보 서비스가 아니며 웹페이지 표시 언어로 지역을 판단하지도 않습니다. 중국 본토 서비스가 해외 IP를 사용하거나, CDN이 여러 지역에 분산되어 있거나, 분류 데이터가 오래된 경우에는 주소 조건을 엄격하게 설정하면 유효한 응답이 걸러질 수 있습니다.
- 단일 도메인을 정확히 일치시키려면
full:example.com을 사용할 수 있습니다. domain:example.com은 해당 도메인과 하위 도메인에 일치합니다.geosite:cn과geoip:cn을 사용하기 전에 현재 실행 중인 코어가 해당 데이터 파일을 읽을 수 있는지 확인하세요.expectIPs는 주소 분류 필터이지 응답의 진위를 증명하는 기능이 아닙니다. 반환된 주소가 특정 지역에 속한다는 이유만으로 응답이 올바르다고 단정할 수 없습니다.
DNS 및 라우팅 설정 합치기
아래 JSON은 전체 노드 설정이 아닙니다. 기존 outbounds에 각각 직접 연결과 정상 작동이 확인된 프록시 연결을 가리키는 direct, proxy 태그가 있다고 가정합니다. 기존 설정의 dns와 routing을 수정하고, 같은 객체에 해당 키를 중복으로 선언하지 마세요.
{
"dns": {
"queryStrategy": "UseIPv4",
"servers": [
{
"address": "223.5.5.5",
"domains": [
"geosite:cn"
],
"expectIPs": [
"geoip:cn"
],
"skipFallback": true
},
"https://1.1.1.1/dns-query"
]
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": [
"223.5.5.5/32"
],
"port": "53",
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"1.1.1.1/32"
],
"port": "443",
"outboundTag": "proxy"
},
{
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:private",
"geoip:cn"
],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
앞의 두 규칙은 DNS 서버 연결에 사용할 출구를 지정합니다. 223.5.5.5:53으로 보내는 조회는 직접 연결하고, 1.1.1.1:443로 보내는 연결은 프록시를 사용합니다. 일반적인 https:// 형식의 DoH는 코어의 라우팅 규칙을 따릅니다. 연결 처리 경로가 다른 +local 형식으로 그대로 바꾸지 마세요. 이 IP 및 포트 규칙은 같은 대상으로 향하는 다른 트래픽에도 적용되며 DNS 내용만 식별하지는 않습니다.
규칙 순서를 임의로 바꾸면 안 됩니다. 먼저 DNS 서버 연결의 출구를 지정해야 DoH 주소가 뒤쪽 IP 분류 규칙에 의해 뜻하지 않게 다른 경로로 전달되는 일을 막을 수 있습니다. 마지막 규칙은 나머지 TCP 및 UDP 트래픽을 아웃바운드 배열의 기본 순서에 맡기지 않고 proxy로 명시적으로 보냅니다. 기존 LAN, 차단, 서비스 규칙이 있다면 하나씩 통합하세요. 전체 설정을 덮어쓴 뒤에도 원래 동작이 유지될 것이라고 가정해서는 안 됩니다.
점검: DNS 서버 연결 출구를 먼저 확인한 뒤 응답 비교
먼저 1.1.1.1:443 연결이 실제로 proxy에 일치하는지 확인한 다음 도메인 조회 결과를 살펴보세요. DNS 주소만 바꾸고 연결 출구를 확인하지 않으면 원격 DNS 조회가 의도한 경로로 전송되는지 검증할 수 없습니다.
직접 연결 아웃바운드의 DNS 처리 방식도 확인하세요
중국 본토 도메인이 도메인 규칙에 일치하면 연결은 direct로 전달됩니다. 이 아웃바운드가 Freedom 프로토콜을 사용하고 기본 DNS 처리 방식을 유지하면 최종 연결에 이 글의 내장 DNS가 아닌 시스템 DNS가 사용될 수 있습니다. 직접 연결 아웃바운드에서 내장 DNS를 명시적으로 사용하려면 기존 아웃바운드를 확인하고 settings.domainStrategy를 조정하세요.
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIPv4"
}
}
다음은 outbounds 배열에 들어가는 객체 하나의 예입니다. 같은 이름의 아웃바운드를 추가하지 말고 기존 direct를 수정하세요. 여기의 UseIPv4와 앞서 설정한 DNS 조회 정책은 문제를 추적하기 쉬운 IPv4 기준 설정을 구성합니다. IPv6를 반드시 비활성화해야 한다는 뜻은 아닙니다.
- IPv4와 IPv6를 함께 사용하려면: DNS 조회 정책과 Freedom의 DNS 처리 방식을
UseIP로 변경할지 검토하고, 로컬 IPv6 연결과 관련 라우팅도 확인하세요. - 프록시 아웃바운드에 도메인을 전달하는 경우: 대상 도메인을 원격에서 조회할 수 있습니다. 따라서 로컬 DNS 응답이 원격에서 실제 사용되는 응답과 다를 수 있습니다.
- 노드 주소가 도메인인 경우: 프록시 서버 자체의 도메인 조회 문제도 고려해야 합니다. 아직 연결되지 않은 프록시 연결만을 노드 도메인의 유일한 조회 경로로 설정하지 마세요.
클라이언트에서 실제 적용된 설정 확인하기
v2rayN은 데스크톱 클라이언트이며, v2rayNG는 Xray 코어를, v2flyNG는 V2Fly 코어를 사용합니다. 클라이언트 인터페이스가 실행 설정을 생성하므로 편집 화면에 필드가 있다고 해서 현재 코어가 그 필드를 사용한다고 볼 수는 없습니다. 이 글은 특정 인터페이스 버전을 전제로 하지 않습니다. 현재 노드, 실행 중인 코어, 최종 생성된 JSON을 확인하세요.
- 기준 설정 저장: 현재 정상 작동하는 설정을 백업하고 노드, 코어 버전, 시스템 프록시 상태, 가상 네트워크 어댑터 사용 여부를 기록하세요. 노드와 전송 매개변수를 동시에 바꾸지 말고 DNS와 관련 라우팅만 한 번에 변경하세요.
- 실행 설정 파일 확인: 최종 JSON에
dns.servers두 항목, 예상한 아웃바운드 태그, 올바른 규칙 순서가 포함되어 있는지 확인하세요. 인터페이스가 설정을 생성하는 경우에는 영구 설정이 저장되는 위치를 수정해야 합니다. 다음 실행 때 덮어써지는 임시 파일만 편집하지 마세요. - 진단 로그 켜기: 잠시
log.loglevel을debug로 설정하고 코어를 재시작한 뒤 요청을 다시 보내세요. 로그 내용은 버전에 따라 다를 수 있으므로 DNS 서버 대상, 일치한 아웃바운드, 오류 정보를 중점적으로 확인하세요. - 각각 테스트:
geosite:cn에 포함된 것이 확인된 도메인 하나와 포함되지 않은 도메인 하나를 선택하세요. 기존 연결을 닫고 필요하다면 앱을 재시작해 새 DNS 동작이 기존 연결 재사용에 가려지지 않게 하세요. - 일반 로그 수준으로 복원: 테스트가 끝나면 로그 수준을
warning또는 원래 값으로 되돌리세요. 로그를 공유하기 전에 노드 주소, 구독 링크, 방문 도메인 등의 정보를 삭제하세요.
해당 코어의 명령줄 도구를 사용할 수 있다면 먼저 설정 파일이 있는 디렉터리에서 구문과 설정 로드를 확인하세요. 아래 명령은 Xray와 V2Fly에서 흔히 사용하는 형식입니다. 실제로 사용하는 코어에 해당하는 명령 하나만 실행하세요. 설정 테스트가 성공해도 업스트림 DNS 서버에 연결할 수 있다는 뜻은 아닙니다.
xray run -test -config config.json
v2ray test -c config.json
nslookup example.com 223.5.5.5 결과만으로 코어의 DNS 분할이 작동한다고 판단하지 마세요. 이 명령은 지정한 DNS 서버에 직접 조회하므로 해당 경로가 작동하는지 확인하는 데는 유용하지만, 이 글의 도메인 분류, 폴백, 프록시 출구 규칙을 거치지 않습니다. 시스템 DNS 테스트와 코어 요청 테스트를 따로 기록해야 합니다.
DNS 오염 방지의 한계와 자주 발생하는 문제
여기서 말하는 DNS 오염 방지는 암호화된 원격 조회, 고정된 연결 출구, 비정상 주소 필터링으로 잘못된 응답을 줄이는 방법이지, 특정 필드 하나가 절대적인 안전을 보장한다는 뜻은 아닙니다. DoH는 DNS 서버까지의 조회 전송을 보호합니다. DNS 서버의 신뢰성, 앱의 별도 조회, 시스템 캐시도 최종 연결에 영향을 줍니다.
중국 본토 웹사이트까지 로딩이 느려졌습니다. 무엇부터 바꿔야 하나요?
먼저 중국 본토 DNS 서버의 expectIPs를 잠시 제거하고 다른 설정은 그대로 둔 채 다시 테스트하세요. 지연이 해소되면 해당 도메인의 실제 응답과 geoip:cn 분류가 일치하는지 확인하세요. 원인을 찾지 않은 채 폴백 서버를 더 추가하지 마세요.
원격 DNS를 설정했는데 로컬 DNS 조회가 계속 보이는 이유는 무엇인가요?
먼저 조회가 브라우저, 시스템, 노드 도메인 조회, 코어 중 어디에서 발생하는지 구분하세요. 앱의 보안 DNS, 시스템 프록시가 적용되는 범위, Freedom의 domainStrategy를 확인하세요. 코어의 DNS 설정은 다른 프로세스가 DNS 조회를 외부로 보내는 것을 자동으로 막지 않습니다.
설정을 저장하자마자 실행이 실패합니다. 어떻게 확인하나요?
먼저 첫 번째 오류가 JSON 구문, 알 수 없는 필드, 분류 데이터 로드 중 어느 문제를 가리키는지 확인하세요. 코어가 geosite.dat와 geoip.dat를 읽을 수 있는지, direct와 proxy가 실제로 존재하는 아웃바운드 태그인지 확인하세요.
DoH는 계속 시간 초과되는데 프록시 노드는 연결됩니다. 왜 그런가요?
1.1.1.1:443 요청이 프록시 아웃바운드에 일치하는지 확인하고 노드에서 DNS 서버까지 연결되는지도 점검하세요. 시스템 시간과 인증서 오류를 확인하고, 실패를 우회하려고 인증서 검증을 끄지 마세요. 필요한 경우 검증할 수 있는 다른 DoH 서버 주소로 바꿔 별도로 비교하세요.
설정을 바꿨는데 웹페이지가 계속 이전 IP로 연결되는 이유는 무엇인가요?
앱을 완전히 종료한 뒤 다시 열고 코어를 재시작한 다음 새 연결로 테스트하세요. 브라우저, 운영체제, 코어, 원격 DNS 서버 모두 캐시를 사용할 수 있습니다. 페이지 새로고침만으로는 기존 연결을 재사용할 수 있어 새 규칙이 적용되지 않았다고 단정할 수 없습니다.
이유를 설명할 수 있는 최소 설정 유지하기
- 먼저 DNS 서버 두 개와 아웃바운드 두 개를 확인한 뒤 사용자 지정 도메인 분류를 단계별로 추가하세요.
- 잘못된 경로로 연결되면 규칙 목록에 원하는 규칙이 있는지만 보지 말고 실제로 일치한 첫 번째 규칙을 찾으세요.
- 특정 도메인을 항상 직접 연결하려면 DNS 일치 조건, 라우팅 우선순위, 직접 연결 아웃바운드의 DNS 처리 방식을 모두 확인하세요.
- 외부로 나가는 DNS 트래픽을 제한하려면 시스템 수준의 가로채기와 네트워크 정책을 별도로 설계해야 합니다. 이 글의 설정 조각을 전체 트래픽 제한 방법으로 사용해서는 안 됩니다.
관리하기 쉬운 DNS 분할 설정이라면 다음 세 가지를 설명할 수 있어야 합니다. 도메인이 왜 해당 DNS 서버를 선택했는지, DNS 서버 연결이 왜 그 아웃바운드를 거치는지, 최종 대상이 왜 직접 연결 또는 프록시 연결되는지입니다. DNS 서버 주소를 계속 추가하기보다 로그와 실행 설정으로 먼저 이 세 가지를 확인하면 문제를 더 쉽게 찾을 수 있습니다.