노드를 가져온 뒤 커널 설정을 이해하고 싶은 사용자를 위한 안내입니다. 요청 흐름에 따라 네 가지 최상위 필드를 살펴보고, VMess + WebSocket + TLS 예시를 분석한 다음 태그 참조, 규칙 순서, DNS를 점검합니다. 글을 읽고 나면 연결에 실패할 때마다 JSON 전체를 다시 작성하는 대신, 인바운드·노드 설정·라우팅 중 어디를 확인해야 하는지 판단할 수 있습니다.
1. 설정 파일과 클라이언트 설정, 먼저 구분하기
v2rayN과 v2rayNG는 노드 관리, 구독 업데이트, 커널 실행 설정 생성을 담당하는 클라이언트입니다. v2rayNG는 Xray 커널을 사용하고, v2flyNG는 v2fly 커널을 사용합니다. v2rayN은 여러 커널을 관리할 수 있지만, 이 글에서 다루는 것은 V2Ray/Xray의 기존 JSON 설정 형식입니다. 모든 커널에 공통으로 적용되는 필드 목록은 아닙니다.
여기서 config.json은 커널이 실제로 읽는 설정 파일을 뜻합니다. 클라이언트의 창 위치나 구독 그룹 등을 저장하는 설정 파일과는 다릅니다. 파일 이름도 항상 고정된 것은 아닙니다. 실행 명령에서 어떤 파일을 지정했는지, 그리고 파일에 inbounds, outbounds 같은 필드가 있는지를 확인하세요. 클라이언트가 노드를 업데이트하거나 커널을 다시 시작하면 자동 생성된 파일이 덮어써질 수 있습니다.
inbounds: 로컬 SOCKS 포트처럼 커널이 요청을 받을 위치를 정의합니다.outbounds: 프록시 노드로 전달하거나 직접 연결하거나 차단하는 등, 커널에서 요청을 내보내는 방식을 정의합니다.routing: 대상 도메인, IP, 인바운드 태그 등의 조건에 따라 사용할 아웃바운드를 선택합니다.dns: 내장 DNS 리졸버를 설정합니다. 시스템 DNS를 자동으로 가로채는 옵션은 아닙니다.
2. 전체 JSON 예시: 인바운드 2개, 아웃바운드 3개
아래는 구조를 살펴보기 위한 전체 예시입니다. node.example.invalid은 실제로 사용할 수 없는 가상 도메인이며 UUID도 예시 값이므로 실제 노드에 연결되지 않습니다. 기존 VMess의 vnext 구조를 사용했으며, 실제 주소·포트·UUID·전송 경로·TLS 이름은 서버 설정을 따라야 합니다.
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"],
"routeOnly": true
}
},
{
"tag": "http-in",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "node.example.invalid",
"port": 443,
"users": [
{
"id": "00000000-0000-4000-8000-000000000001",
"alterId": 0,
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "node.example.invalid"
},
"wsSettings": {
"path": "/ws",
"headers": {
"Host": "node.example.invalid"
}
}
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": ["full:blocked.example.invalid"],
"outboundTag": "block"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["full:localhost"],
"outboundTag": "direct"
}
]
},
"dns": {
"servers": ["223.5.5.5"]
}
}
여기 나온 포트는 설명을 위한 예시이며 모든 버전의 기본값은 아닙니다. JSON에서 포트는 숫자로, true는 불리언으로 작성해야 하며 따옴표를 붙인 문자열로 쓰면 안 됩니다. 마지막 항목 뒤에는 쉼표를 붙일 수 없습니다. 검증하기 쉽도록 예시에는 주석을 넣지 않았습니다.
3. inbounds: 수신 주소, 프로토콜, 스니핑
listen은 연결을 받을 로컬 주소를, port는 포트를, protocol은 앱이 사용할 프록시 프로토콜을 지정합니다. SOCKS 클라이언트는 HTTP 인바운드에 직접 연결할 수 없습니다. 포트 연결에 성공해도 프로토콜이 맞다는 뜻은 아닙니다. 앱에 수동으로 설정할 경우, 예시는 SOCKS5 127.0.0.1:10808 또는 HTTP 프록시 127.0.0.1:10809에 해당합니다.
SOCKS 인바운드
- tag
- socks-in
- listen
- 127.0.0.1
- port
- 10808
- protocol
- socks
- settings.udp
- true
로컬 기기에서만 수신합니다. UDP를 사용하려면 앱에서 SOCKS5 UDP 릴레이도 지원해야 합니다.
HTTP 인바운드
- tag
- http-in
- listen
- 127.0.0.1
- port
- 10809
- protocol
- http
- settings
- 빈 객체
HTTP 프록시를 지원하는 앱에 적합합니다. HTTPS 요청은 보통 CONNECT 터널을 사용합니다.
127.0.0.1로 설정하면 로컬 기기에서만 연결을 받습니다. 0.0.0.0으로 바꾸면 모든 IPv4 네트워크 인터페이스에서 수신합니다. 예시 SOCKS 인바운드에는 auth: "noauth"도 설정되어 있으므로 그대로 복사해 네트워크에 노출해서는 안 됩니다. 프록시를 공유해야 한다면 인증, 방화벽, 접근 허용 대상을 함께 점검하세요.
sniffing은 HTTP Host 또는 TLS 핸드셰이크의 서버 이름을 확인해 대상 도메인을 식별하고, 도메인 규칙이 적용되도록 돕습니다. routeOnly: true는 스니핑한 이름을 라우팅 판단에만 사용하고 원래 연결 대상을 대체하지 않는다는 뜻입니다. HTTPS를 복호화하는 기능은 아니며, 모든 트래픽에서 도메인을 알아낼 수 있는 것도 아닙니다. 이 예시에서는 SOCKS 인바운드에만 스니핑을 설정했습니다.
tag는 설정 내부에서 참조하는 이름이며, 서버에 표시되는 사용자 이름이 아닙니다.settings.udp: true를 설정해도 모든 UDP 트래픽이 자동으로 커널에 전달되거나 TUN이 활성화되는 것은 아닙니다.- Android 클라이언트의 VPN 트래픽 처리 방식은 이 두 로컬 수신 포트만으로 설명할 수 없습니다. 이 예시는 주로 수동 프록시 진입점을 이해하기 위한 것입니다.
4. outbounds: 노드 인증과 전송 계층 구분하기
프록시 아웃바운드에서 protocol: "vmess"는 노드 프로토콜을 뜻합니다. settings.vnext에는 서버 목록이, users에는 인증 정보가 들어갑니다. id는 사용자 UUID입니다. alterId: 0은 최신 VMess에서 일반적으로 사용하는 설정이므로, 오래된 가이드의 0이 아닌 값을 무작정 적용하지 마세요. users[].security: "auto"는 VMess 암호화 옵션이며 TLS 활성화 여부와는 별개입니다.
| 필드 | 예시 값 | 실제 역할 |
|---|---|---|
vnext[].address | node.example.invalid | 커널이 연결할 노드 주소 |
vnext[].port | 443 | 서버가 수신하는 포트. 로컬 인바운드 포트가 아닙니다. |
streamSettings.network | ws | WebSocket 전송 사용 |
streamSettings.security | tls | 전송 계층에서 TLS 활성화 |
tlsSettings.serverName | node.example.invalid | TLS 서버 이름. 일반적으로 SNI와 인증서 이름 검증에 사용됩니다. |
wsSettings.path | /ws | 서버 설정과 일치해야 하는 WebSocket 요청 경로 |
wsSettings.headers.Host | node.example.invalid | WebSocket 핸드셰이크에 사용하는 HTTP Host |
예시에서는 변수를 줄이기 위해 주소, SNI, Host를 같은 값으로 설정했지만 실제 구성에서는 서로 다를 수 있습니다. IP 주소로 연결하더라도 TLS에서 도메인 이름을 요구할 수 있습니다. 경로도 정확히 일치해야 합니다. /ws와 /proxy는 서로 바꿔 쓸 수 있는 장식용 텍스트가 아닙니다.
freedom은 직접 연결 아웃바운드, blackhole은 차단 아웃바운드를 뜻합니다. direct, block, proxy는 이 글에서 정한 태그 이름이므로 바꿀 수 있지만, 모든 outboundTag 참조도 함께 수정해야 합니다. VLESS 아웃바운드의 사용자 필드는 VMess와 완전히 같지 않습니다. protocol만 vless로 바꾼다고 전환이 끝나는 것은 아닙니다.
확인: 연결에 실패하면 두 계층의 설정부터 점검
주소, 포트, UUID를 먼저 확인한 뒤 network, TLS 이름, Host, path를 비교하세요. serverName을 바로잡는 대신 인증서 검증을 끄지 마세요. 검증을 건너뛴다고 잘못된 설정이 올바른 노드로 바뀌지는 않습니다.
5. routing: 규칙 순서와 기본 아웃바운드
rules는 배열 순서대로 확인하며, 처음 일치하는 규칙이 아웃바운드를 결정합니다. 예시에서는 먼저 테스트용 도메인을 차단한 다음 사설 주소와 localhost를 직접 연결합니다. 어떤 규칙에도 일치하지 않으면 기존 V2Ray/Xray 설정은 outbounds 배열의 첫 번째 아웃바운드를 사용하므로 여기서는 기본적으로 proxy로 연결됩니다. 이 기본 동작은 태그 이름이 ‘proxy’인지와 관계없습니다.
- 태그 확인:
outboundTag: "direct"에 해당하는tag: "direct"아웃바운드가 있어야 합니다. - 순서 확인: 구체적인 예외 규칙은 대체로 포괄적인 규칙보다 앞에 둡니다. 마지막에 적용할 기본 규칙을 앞쪽에 놓으면 뒤의 규칙이 가려집니다.
- 조건 확인: 한 규칙 안의 서로 다른 필드는 대체로 모두 충족해야 합니다. 한 필드의 배열에 있는 여러 후보는 보통 하나라도 일치하면 적용됩니다.
- 데이터 확인:
geoip:private를 사용하려면 GeoIP 데이터 파일이 있어야 합니다.geosite항목을 쓸 때도 해당 도메인 데이터가 준비되어 있는지 확인하세요.
도메인 매칭 문법은 서로 다릅니다. full:example.com은 도메인 전체가 정확히 일치할 때만 적용되며, domain:example.com은 해당 도메인과 하위 도메인에 적용됩니다. 접두사 없는 문자열은 보통 키워드로 매칭되어 예상보다 많은 대상에 적용될 수 있습니다. 정확한 예외 규칙을 만들 때는 매칭 범위를 명시하세요.
| domainStrategy | DNS 조회 시점 | 점검할 사항 |
|---|---|---|
AsIs | 라우팅 판단 과정에서 도메인을 IP로 자동 조회하지 않습니다. | 도메인 요청이 IP 규칙과 자동으로 일치할 것이라고 기대하면 안 됩니다. |
IPIfNonMatch | 도메인 규칙이 일치하지 않으면 IP 조회 후 IP 규칙을 다시 적용합니다. | 조회 결과에 따라 최종 아웃바운드가 달라질 수 있습니다. |
IPOnDemand | 매칭에 IP 조건이 필요한 경우 DNS 조회를 수행합니다. | 조회 비용과 DNS 응답 결과를 확인하세요. |
이 예시의 AsIs는 판단 과정을 단순하게 유지하기 위한 설정입니다. 대상이 원래 사설 IP라면 사설 주소 규칙과 일치할 수 있지만, 사설 IP로 해석되는 도메인까지 반드시 해당 규칙에 일치하는 것은 아닙니다. 인트라넷 도메인에는 명시적인 직접 연결 도메인 규칙을 추가하거나, DNS 조회 동작을 이해한 뒤 정책을 조정하세요.
6. dns: 내장 DNS 리졸버와 시스템 DNS는 다릅니다
dns.servers는 커널 내장 DNS 리졸버에서 사용할 서버를 지정합니다. 이 예시에는 구조 설명을 위해 업스트림 서버 223.5.5.5 하나만 설정했습니다. 완전한 DNS 분할 설정을 구현한 것은 아닙니다. 앱이 요청을 보내기 전에 직접 DNS 조회를 할 수도 있으므로 시스템, 브라우저, 커널의 조회 경로를 각각 확인해야 합니다.
- 앱이 도메인을 전달하는 경우: 커널이 도메인 규칙으로 라우팅을 판단할 수 있습니다. 라우팅 정책에 IP가 필요하면 내장 DNS로 주소를 조회합니다.
- 앱이 먼저 조회한 뒤 IP를 전달하는 경우: 라우팅에 IP만 전달될 수 있습니다. 스니핑으로 일부 도메인 정보를 보완할 수 있지만 모든 요청을 복원할 수 있는 것은 아닙니다.
- 직접 연결 아웃바운드의 DNS 조회:
freedom의 도메인 처리 정책도 조회 방식에 영향을 줍니다. 이 예시처럼 별도 설정이 없다고 해서 모든 DNS 조회가 앞서 설명한 내장 업스트림을 거치는 것은 아닙니다. - 원격 프록시의 DNS 조회: 도메인이 프록시 프로토콜을 통해 서버로 전달되면 서버에서 조회할 수 있습니다. 실제 요청과 설정에 따라 달라집니다.
따라서 dns를 설정했다는 사실만으로 모든 DNS 조회가 의도한 대로 프록시를 통과한다고 단정할 수 없습니다. 앱의 자체 DNS 조회 여부, 라우팅의 domainStrategy, 아웃바운드의 DNS 처리 정책, DNS 서버 연결 상태를 함께 확인하세요. 특히 도메인 조회가 필요한 노드에 연결할 때는, 노드 연결이 아직 성립하지 않았는데 해당 노드에 의존해 노드 도메인을 조회하는 상황을 피해야 합니다.
7. 설정 내보내기부터 문제 해결까지: 한 번에 하나씩 변경
문제를 해결할 때는 먼저 실행 가능한 설정을 백업한 뒤 커널 버전과 실제로 읽는 파일을 확인하세요. v2rayN의 ‘설정’ → ‘매개변수 설정’에서 로컬 수신 관련 매개변수를 확인하거나 변경할 수 있습니다. 메뉴와 옵션 이름은 버전에 따라 다를 수 있습니다. 클라이언트 화면의 노드 설정, 라우팅 설정, 실행 중인 JSON이 서로 일치하는지 확인하세요. 클라이언트가 다시 생성하는 파일 하나만 확인해서는 안 됩니다.
- 문법 확인: 로컬 편집기에서 괄호, 쉼표, 값의 자료형을 확인하세요. UUID, 구독 주소, 노드 정보가 포함된 파일을 공개 온라인 포맷터에 올리지 마세요.
- 커널 호환성 확인: 설정을 읽는 커널이 V2Ray인지 Xray인지 확인하세요. 새 필드와 전송 방식은 현재 커널에서 지원하는 범위를 따라야 합니다.
- 연결 지점 확인: 프로세스가 설정된 포트에서 실제로 수신 중인지 확인하세요.
address already in use오류가 나타나면 노드 UUID를 바꾸기 전에 포트 충돌부터 해결하세요. - 아웃바운드 확인: 우선 규칙 변수를 줄이고 주소, 인증, 전송 설정을 확인하세요. 시간 초과, 인증 실패, TLS 오류는 각각 다른 원인부터 점검해야 합니다.
- 분할 라우팅 확인: 범위가 명확한 테스트 규칙을 하나 추가해 요청이 의도한 아웃바운드를 선택하는지 확인한 뒤 전체 규칙을 복구하세요.
- 디버그 로그 원복: 필요한 경우
loglevel을 잠시debug로 변경하세요. 점검을 마치면warning으로 되돌려 연결 정보가 과도하게 기록되지 않도록 합니다.
커널을 직접 실행할 때는 해당 커널의 설정 테스트 명령을 사용할 수 있습니다. 아래 명령은 하위 명령 형식을 사용하는 현재 V2Ray/Xray 실행 파일을 기준으로 하며, 경로를 실제 파일 위치로 바꿔야 합니다. 구버전은 명령줄 인자가 다를 수 있으므로 먼저 로컬 help 출력을 확인하세요.
v2ray test -c config.json
xray run -test -config config.json
테스트에 성공했다는 것은 현재 커널이 설정을 읽고 불러올 수 있다는 뜻일 뿐, 노드가 온라인 상태이거나 인증서가 올바르거나 모든 규칙이 의도대로 작동한다는 뜻은 아닙니다. 마지막으로 프록시를 지원하는 앱에서 실제 요청을 보내 확인하세요. 로그에서는 인바운드 태그, 대상 주소, 선택된 아웃바운드를 확인하면 됩니다. 로그를 공유하기 전에는 인증 정보와 개인 접속 기록을 삭제하세요.
정리: 인바운드·아웃바운드·라우팅·DNS를 단계별로 확인
요청이 올바른 포트로 들어오는지 확인하고, 프록시 노드가 작동하는지 검증한 다음 분할 라우팅과 DNS 정책을 추가하세요. 단계마다 복구할 수 있는 설정 사본을 남겨 두면 여러 계층을 한꺼번에 바꾼 뒤 ‘여전히 연결되지 않는다’는 상황을 피할 수 있습니다.