V2Ray 사용자 지정 라우팅 규칙 설정법: domain·ip·geosite 매칭 문법과 우선순위

domain, full, regexp, geosite, geoip 매칭 접두사의 문법과 차이, 규칙의 위에서 아래로 적용되는 순서, 자주 발생하는 충돌 해결법을 정리합니다.

이 글의 핵심

구독을 가져온 뒤 v2rayN에서 트래픽 분기를 설정하려는 사용자를 위한 안내입니다. 먼저 도메인 매칭과 IP 매칭을 구분하고, 첫 번째 규칙 우선 적용 원칙과 DNS 해석 전략, 아웃바운드 태그를 알아봅니다. 본문의 JSON은 핵심 설정 예시이며 바로 실행할 수 있는 전체 설정 파일은 아닙니다. 예시를 기준으로 생성된 설정을 확인하면 규칙이 적용되지 않거나 예외가 포괄 규칙에 묻히는 문제를 파악할 수 있습니다.

1. 라우팅 규칙: 요청이 어느 아웃바운드로 나갈지 결정

구독에는 노드 연결 정보가 포함되고, 라우팅은 각 요청에 어떤 노드를 사용할지 결정합니다. VMess, VLESS 등은 노드 연결 프로토콜이지 라우팅 매칭 접두사가 아닙니다. 노드를 VLESS로 바꿔도 특정 사이트의 직접 연결 또는 프록시 사용 여부가 자동으로 바뀌지는 않습니다.

요청이 코어에 들어옴 대상 정보 확인 규칙을 순서대로 매칭 아웃바운드 태그 선택 대상에 연결

V2Ray 및 Xray에서 흔히 사용하는 라우팅 구성에서 routing.rules는 순서가 있는 배열입니다. 각 규칙은 대상 도메인, 대상 IP, 포트 또는 인바운드 태그 등의 조건을 확인하고, 조건이 맞으면 outboundTag로 지정된 아웃바운드를 선택합니다. 태그는 설정에 정의된 이름일 뿐이며 proxy나 direct가 기본 아웃바운드로 자동 제공되는 것은 아닙니다.

2. domain, full, regexp: 매칭 범위에 맞는 접두사 선택

domain은 규칙의 필드 이름이기도 하고, 필드 값에 쓰이는 매칭 접두사이기도 합니다. 아래 표의 문자열은 모두 "domain": [...] 배열에 넣습니다. URL의 프로토콜, 경로, 쿼리 문자열은 입력하지 마세요. 라우팅의 도메인 매칭은 브라우저 주소창의 URL 매칭과 다릅니다.

문법매칭 범위주요 경계 사례
full:example.com완전히 일치하는 도메인만example.com과 일치하지만 www.example.com과는 일치하지 않음
domain:example.com최상위 도메인과 하위 도메인example.com, a.example.com과 일치하지만 notexample.com과는 일치하지 않음
example.com일반 문자열 포함 매칭도메인 경계 매칭보다 범위가 넓어 notexample.com과도 일치할 수 있음
regexp:^api[0-9]+[.]example[.]com$정규식 매칭api1.example.com과 일치하지만 api.example.com과는 일치하지 않음
geosite:cn데이터 파일에 포함된 도메인 목록로컬 데이터 파일에 cn 태그가 있는지와 해당 태그의 실제 내용에 따라 다름

특정 호스트 하나만 프록시로 보내려면 full:을 사용하세요. 사이트 전체와 하위 도메인을 함께 처리하려면 domain:을 사용하면 됩니다. 일반 문자열은 포함 매칭이 필요한 경우에만 적합하며, 정확한 도메인을 간단히 쓰는 방식으로 사용하지 않는 것이 좋습니다. domain:*.example.com처럼 입력하지 마세요. 와일드카드 문법이 아닙니다.

{
  "type": "field",
  "domain": [
    "full:login.example.com",
    "domain:example.net",
    "regexp:^api[0-9]+[.]example[.]com$"
  ],
  "outboundTag": "proxy"
}

위 배열의 세 항목은 OR 조건입니다. 도메인 조건 중 하나라도 일치하면 됩니다. 정규식에서 [.]는 점 문자를 그대로 나타내므로 JSON의 백슬래시 이스케이프와 혼동할 일이 없습니다. 정규식의 \.를 사용하려면 JSON 문자열 안에는 \\.로 써야 합니다. 처음의 ^와 끝의 $는 전체 문자열에 일치하도록 범위를 제한합니다.

3. ip, geoip, geosite: IP 주소 목록과 도메인 목록 구분하기

ip 필드에는 IP 주소, CIDR 대역 또는 geoip: 목록을 넣고, domain 필드에는 도메인 매칭 항목이나 geosite: 목록을 넣습니다. 두 종류의 목록은 서로 바꿔 쓸 수 없습니다. geoip:cn은 주소의 지역 분류를 뜻하며 중국어 웹사이트 전체를 의미하지 않습니다. geosite:cn은 도메인 목록이며, 해당 도메인이 언제나 같은 지역의 주소로 해석된다는 보장도 없습니다.

{
  "type": "field",
  "ip": [
    "192.168.0.0/16",
    "10.0.0.0/8",
    "geoip:private"
  ],
  "outboundTag": "direct"
}

이 예시는 사설망 대상에 직접 연결하는 방법을 보여줍니다. 앞의 두 대역은 geoip:private와 겹칠 수 있으므로 실제 설정에서는 필요한 대역이나 목록 중 하나만 선택해도 됩니다. 중국 본토 도메인과 중국 본토 IP 주소에 모두 직접 연결하려면 규칙을 두 개로 나누는 것이 좋습니다. 하나는 domain, 다른 하나는 ip를 사용하세요. 두 필드를 한 규칙에 함께 넣고 OR 조건으로 처리되기를 기대하지 마세요.

4. 첫 번째로 일치하는 규칙 적용: 예외를 먼저, 포괄 규칙은 나중에

규칙은 배열 순서대로 검사하며, 처음 일치한 규칙으로 라우팅이 결정됩니다. 더 구체적인 규칙이라고 자동으로 우선 적용되지는 않습니다. domain:example.com을 직접 연결 규칙으로 먼저 쓰고 full:api.example.com을 프록시 규칙으로 나중에 쓰면, 뒤의 규칙은 앞의 규칙에 가려집니다.

{
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "domain": ["full:api.example.com"],
        "outboundTag": "proxy"
      },
      {
        "type": "field",
        "domain": ["domain:example.com"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

이 설정은 특정 호스트의 프록시 예외를 먼저 처리하고, 도메인 전체의 직접 연결을 다음에 처리한 뒤, 나머지 TCP 및 UDP 요청을 프록시로 보냅니다. routing만 보여주는 예시이므로 proxy와 direct라는 아웃바운드가 미리 정의되어 있어야 합니다. 어떤 규칙에도 일치하지 않으면 첫 번째 아웃바운드가 사용되는 경우가 많습니다. 태그 이름만 보고 기본 경로를 추측하지 마세요.

  1. 구체적인 예외를 먼저 지정하세요. 로그인 API, 내부 서비스, 고정 출구를 사용해야 하는 도메인 등이 여기에 해당합니다.
  2. 분류 규칙을 추가하세요. 확인된 geosite 및 geoip 분류를 이어서 설정합니다.
  3. 기본 동작을 정하세요. 마지막의 포괄 규칙이나 첫 번째 아웃바운드를 확인해 요청이 의도치 않게 직접 연결되지 않도록 하세요.
  4. 생성된 규칙 순서를 확인하세요. 클라이언트가 기본 규칙과 사용자 지정 규칙을 함께 생성할 수 있으므로 GUI 목록이 최종 배열 전체와 같지 않을 수 있습니다.

포트 조건도 매칭 범위를 바꿉니다. 도메인 규칙에 "port": "443"을 추가하면 대상 포트가 443인 요청만 처리됩니다. 같은 도메인이라도 80번 포트 연결은 일치하지 않습니다. 사이트 전체에 같은 프록시를 적용하려는 경우 포트 제한을 실수로 추가하지 않도록 주의하세요.

5. domainStrategy: 도메인을 언제 IP로 해석할까

도메인 규칙을 올바르게 작성해도 IP 규칙이 일치하지 않을 수 있습니다. 원인은 대개 DNS 해석 시점에 있습니다. routing.domainStrategy는 라우팅 매칭 과정에서 도메인을 IP 주소로 해석할지 결정하며, DNS 조회가 반드시 프록시를 통과하도록 보장하지는 않습니다. 코어 DNS, 아웃바운드의 DNS 해석, 클라이언트 DNS 설정도 각각 확인해야 합니다.

AsIs: 기존 대상 정보로 먼저 매칭

설정 필드
routing.domainStrategy
설정 값
AsIs
도메인 요청
라우팅 매칭을 위해 IP를 별도로 조회하지 않음
IP 요청
ip 조건으로 계속 매칭 가능

주로 도메인 규칙을 사용하고 라우팅 단계의 DNS 조회를 줄이려는 경우에 적합합니다.

IPIfNonMatch: 일치하는 규칙이 없을 때 조회

설정 필드
routing.domainStrategy
설정 값
IPIfNonMatch
실행 조건
도메인 대상이 기존 규칙과 일치하지 않음
이후 동작
DNS 해석 후 다시 매칭 시도

앞선 포괄 규칙에 이미 일치하면, 규칙 미일치 후 DNS를 조회하는 과정은 실행되지 않습니다.

자주 쓰이는 또 다른 값은 IPOnDemand입니다. 매칭 중 IP가 필요한 규칙을 만나면 대상 도메인을 조회할 수 있습니다. 따라서 IP 규칙을 앞쪽에 배치하면 DNS 조회가 일찍 발생할 수 있습니다. 전략을 선택하기 전에 도메인 분류와 주소 분류 중 어느 쪽을 우선할지 정하고 규칙 순서를 조정하세요. 전략을 바꾸는 것만으로 모든 문제가 해결되지는 않습니다.

6. v2rayN에서 확인하기: 생성된 설정과 연결 로그 살펴보기

현재 라우팅 설정을 먼저 백업한 뒤 v2rayN의 라우팅 설정에서 규칙을 편집하세요. 데스크톱 UI에 따라 메뉴 이름이 다를 수 있으므로 사용 중인 버전에서 표시되는 라우팅 설정과 규칙 편집 화면을 기준으로 삼으세요. 본문의 JSON은 V2Ray/Xray 코어 필드 예시이며, 도메인 목록만 입력할 수 있는 칸에 그대로 붙여 넣으면 안 됩니다.

443
일반적인 HTTPS 대상 포트
53
전통적인 DNS에서 주로 사용하는 포트
1–65535
규칙에 지정할 수 있는 포트 범위

이 숫자는 포트의 용도를 나타내며 속도 측정 결과가 아닙니다. 443번 포트가 모든 웹 트래픽을 뜻하지는 않고, 53번 포트가 모든 암호화 DNS를 포함하지도 않습니다. 포트를 기준으로 트래픽을 나눌 때는 실제 전송 방식도 고려해야 하며, 포트 번호만으로 앱의 용도를 단정해서는 안 됩니다.

  1. 입력 형식을 확인하세요. JSON에는 영문 큰따옴표를 사용하고 주석과 마지막 쉼표를 넣지 마세요. 코어 필드 이름은 그대로 유지해야 합니다.
  2. 실행 중인 코어를 확인하세요. 의도한 코어가 선택되어 있는지, 클라이언트가 최종적으로 생성한 규칙 문법이 올바른지 확인하세요. 다른 형식의 설정 필드를 섞어 쓰지 마세요.
  3. 태그와 리소스를 확인하세요. outboundTag가 실제로 정의되어 있는지, 목록 태그를 불러올 수 있는지 확인하세요. 트래픽 분기를 테스트하기 전에 코어 시작 오류부터 해결해야 합니다.
  4. 새 연결을 다시 만드세요. 라우팅을 저장하고 적용한 뒤 테스트 앱의 기존 연결을 종료하고 새 요청을 보내세요. 이미 연결된 장시간 연결은 규칙 목록이 바뀌어도 자동으로 다른 아웃바운드로 전환되지 않습니다.
  5. 접속 로그를 확인하세요. 로그 상세 정보에서 대상 도메인 또는 IP, 대상 포트, 인바운드 및 아웃바운드 태그를 확인하세요. 필요하면 로그 수준을 잠시 높이고 테스트가 끝난 뒤 원래대로 돌리세요.

도메인 규칙을 검증할 때는 최소 세 가지 대상을 준비하세요. 정확한 예외인 api.example.com, 같은 도메인의 다른 호스트인 www.example.com, 해당 도메인에 속하지 않는 대상입니다. 앞의 두 항목으로 full:과 domain:의 차이를 확인하고, 세 번째 항목으로 기본 동작을 확인할 수 있습니다. 예시 도메인은 매칭 범위를 설명하기 위한 것입니다. 연결 테스트에는 사용 권한이 있고 실제 서비스가 제공되는 도메인을 사용하세요.

7. 자주 묻는 문제: 규칙 덮어쓰기, 주소 정보, 목록 오류부터 확인

프록시 규칙만 추가했는데 왜 직접 연결되나요?

먼저 해당 규칙 앞에 범위가 더 넓은 직접 연결 규칙이 있는지 확인하세요. 정확한 예외를 포괄 목록보다 앞에 옮기고 적용한 다음 새 연결을 만든 뒤, 로그에서 아웃바운드 태그를 확인하세요. 생성된 설정의 순서가 GUI와 다르다면 기본 규칙이 먼저 일치하는지도 살펴보세요.

domain 규칙을 작성했는데 로그에는 IP만 표시됩니다. 어떻게 해야 하나요?

먼저 앱이 로컬에서 이미 DNS 조회를 마쳤는지, 인바운드가 도메인 정보를 전달하는지 확인하세요. 이어서 현재 코어의 스니핑 설정을 살펴보세요. 스니핑은 지원되는 트래픽에서만 정보를 가져올 수 있으므로 모든 연결의 도메인을 복원한다고 보장할 수 없습니다. 고정된 내부망 대상은 명시적인 IP 또는 네트워크 대역 규칙으로 처리할 수 있습니다.

geosite를 추가한 뒤 코어가 시작되지 않습니다. 무엇을 수정해야 하나요?

먼저 로그에서 리소스 파일 경로와 태그 이름을 확인하세요. 현재 데이터 파일에 사용 중인 태그가 있는지 확인하고, 필요하면 클라이언트의 리소스 업데이트 메뉴를 통해 업데이트하세요. 우선 full: 규칙 하나로 기본 라우팅을 확인한 뒤 목록을 다시 적용하면 여러 설정을 동시에 바꾸는 일을 피할 수 있습니다.

노드를 바꾼 뒤 규칙이 작동하지 않습니다. 프로토콜이 트래픽 분기를 지원하지 않는 건가요?

보통은 VMess나 VLESS 탓으로 보기보다 생성된 설정부터 확인해야 합니다. 노드를 바꾼 뒤에도 규칙이 올바른 프록시 아웃바운드를 참조하는지, 현재 라우팅 설정이 선택되어 있는지, 다른 사용자 지정 설정으로 전환되지 않았는지 확인하세요. 노드 연결 실패와 잘못된 아웃바운드 선택은 서로 다른 문제이므로 로그를 따로 확인해야 합니다.

안정적으로 설정하려면 먼저 정확한 도메인 하나로 아웃바운드를 확인하고, 그다음 하위 도메인이나 목록으로 범위를 넓힌 뒤, 마지막에 IP 조건과 기본 규칙을 추가하세요. 한 번에 한 종류의 조건만 바꾸고 언제든 되돌릴 수 있도록 기존 라우팅 설정을 보관하세요. 기본 개념은 개념 빠른 참조에서 확인할 수 있습니다. DNS와 트래픽 분기 연동을 계속 점검하려면 고급 설정을 참고하세요.

클라이언트 다운로드 및 설치