본문으로 건너뛰기

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

domain, full, regexp, geosite, geoip 매칭 방식과 규칙의 위에서 아래로 적용되는 순서를 살펴보고, 바로 수정해 쓸 수 있는 규칙 예제를 제공합니다.

이 글 미리보기

구독을 가져온 뒤 v2rayN의 트래픽 분기 규칙을 조정하려는 사용자를 위한 안내입니다. 먼저 도메인 매칭과 IP 매칭을 구분하고, ‘명시적 예외, 분류 규칙, 최종 기본 규칙’ 순서로 구성하세요. 예제는 V2Ray/Xray의 field 라우팅 구조를 사용한 수정 가능한 JSON 조각입니다. 적용 전 실제 코어, 아웃바운드 태그, 규칙 데이터베이스를 확인하세요. 이 조각은 완성된 클라이언트 설정이 아니므로 그대로 실행하면 안 됩니다.

1. 라우팅 규칙의 기본 구조

라우팅 규칙은 구독 노드 목록과 다릅니다. 구독은 서버 연결 정보를 제공하고, 라우팅은 각 연결을 어느 아웃바운드로 보낼지 결정합니다. VMess 또는 VLESS 노드를 바꿔도 잘못 작성한 도메인 조건이 자동으로 수정되지는 않습니다. 아래에서는 direct, proxy, block을 각각 직접 연결, 프록시, 차단을 뜻하는 태그로 사용합니다. 실제 설정의 아웃바운드에 해당 태그가 있어야 합니다.

연결이 코어에 진입 대상 정보 추출 규칙을 순서대로 확인 아웃바운드 태그 선택 아웃바운드에서 연결 처리

가장 간단한 규칙은 ‘무엇을 매칭할지’와 ‘어디로 보낼지’만 지정하면 됩니다. 다음 객체는 example.com과 그 하위 도메인을 프록시 아웃바운드로 보냅니다. 이는 routing.rules 배열에 들어가는 요소 하나일 뿐, 완성된 설정이 아닙니다. 이 글의 example.com은 문법 설명용 도메인이므로 실제 사용 시 대상 도메인으로 바꾸세요.

{
  "type": "field",
  "domain": ["domain:example.com"],
  "outboundTag": "proxy"
}

예를 들어 domain과 port: "443"을 같은 객체에 넣으면 도메인 조건과 대상 포트 443을 모두 충족해야 매칭됩니다. 둘 중 하나만 만족해도 적용된다는 뜻이 아닙니다. ‘도메인 또는 IP’ 조건이 필요하면 보통 두 필드를 한 규칙에 넣지 말고 규칙을 두 개로 나눕니다.

2. domain, full, regexp 선택하기

domain은 JSON 필드 이름이면서 필드 안에서 사용할 수 있는 매칭 접두사이기도 합니다. 둘을 혼동하지 마세요. 필드에 일반 문자열을 지정하면 기본적으로 부분 문자열을 기준으로 매칭되어 예상보다 넓은 범위가 적용될 수 있습니다. 특정 사이트와 하위 도메인을 지정하려면 domain:을 우선 사용하세요.

표기법매칭 범위사용 시 참고
full:api.example.com해당 도메인만하위 도메인은 포함하지 않음
domain:example.com루트 도메인과 하위 도메인notexample.com에는 매칭되지 않음
example.com도메인에 이 문자열이 포함됨매칭 범위가 넓어질 수 있음
regexp:...정규식에 일치하는 도메인앵커와 JSON 이스케이프에 유의
geosite:cn도메인 데이터베이스의 cn 분류로드된 데이터베이스 내용에 따라 달라짐

도메인 필드에는 웹페이지 경로 문법을 사용할 수 없습니다. https://api.example.com/v1/items를 매칭하려면 full:api.example.com을 지정하세요. 프로토콜, 슬래시, 경로를 함께 넣으면 안 됩니다. 일반 라우팅 규칙으로는 같은 HTTPS 사이트의 서로 다른 페이지 경로를 구분할 수도 없습니다.

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

여기 세 가지 조건은 ‘또는’ 관계이므로 하나라도 일치하면 프록시를 선택합니다. 정규식은 edge1.example.net, edge23.example.net처럼 번호가 붙은 도메인을 매칭합니다. JSON의 \\.는 파싱된 뒤 정규식의 \.가 됩니다. 백슬래시를 한 단계 덜 입력하면 파싱 오류가 나거나 의미가 달라질 수 있습니다.

3. ip, geoip, geosite의 차이

geosite는 도메인을 분류하고 geoip는 IP를 분류합니다. 서로 다른 데이터를 사용하므로 대체할 수 없습니다. geosite:cn은 ‘조회 결과가 중국 본토에 있는 모든 도메인’을 뜻하지 않습니다. geoip:cn도 서버의 콘텐츠가 반드시 중국 본토 웹사이트에 속한다는 의미는 아닙니다. CDN, 공유 주소, 데이터베이스 업데이트에 따라 결과가 달라질 수 있습니다.

도메인 분류 규칙

필드
domain
예시
geosite:cn
데이터 출처
로드된 geosite 도메인 데이터베이스
매칭 기준
연결에서 확인할 수 있는 대상 도메인

먼저 해당 분류가 있는지 확인한 뒤 도메인이 데이터베이스에 포함되어 있는지 살펴보세요. 분류가 실시간으로 자동 판별되는 것은 아닙니다.

IP 분류 규칙

필드
ip
예시
geoip:cn
데이터 출처
로드된 geoip 주소 데이터베이스
매칭 기준
대상 IP 또는 라우팅 과정에서 확인된 주소

도메인 연결에서 주소 조회가 이루어지는지는 domainStrategy 등 설정에 따라 달라집니다.

명확한 사설 네트워크 대역은 CIDR로 직접 지정하면 사이트 분류에 의존하지 않고 로컬 기기에 직접 연결할 수 있습니다. 아래 예시는 흔히 사용하는 IPv4 사설 대역 세 가지를 직접 연결로 보냅니다. 모든 특수 용도 주소를 포함하지 않으며 IPv6 로컬 주소도 포함하지 않습니다. 더 넓은 범위가 필요하다면 데이터베이스의 geoip:private를 사용할 수 있지만, 실제로 어떤 주소가 포함되는지 확인하세요.

{
  "type": "field",
  "ip": [
    "10.0.0.0/8",
    "172.16.0.0/12",
    "192.168.0.0/16"
  ],
  "outboundTag": "direct"
}
/32
IPv4 단일 주소의 CIDR 접두사
/128
IPv6 단일 주소의 CIDR 접두사
443
HTTPS에서 흔히 사용하는 대상 포트

이 값은 주소와 프로토콜의 기본 정보이지 속도 측정 결과가 아닙니다. 포트 조건은 연결의 대상 포트를 지정합니다. 예를 들어 "port": "443"은 v2rayN의 로컬 수신 포트가 아닙니다. 포트 443만으로 트래픽을 분기하면 여러 웹사이트에 영향을 주므로 보통 도메인 같은 조건과 함께 사용합니다.

4. 우선순위: 먼저 매칭되면 종료

규칙은 배열 순서대로 위에서 아래로 확인하며, 한 규칙에 매칭되면 해당 아웃바운드를 선택하고 이후의 ‘더 구체적인’ 규칙은 확인하지 않습니다. 완전한 도메인이라고 앞선 분류 규칙보다 우선 적용되는 것은 아니며, 긴 네트워크 대역도 앞에 있는 짧은 대역보다 자동으로 우선하지 않습니다. 정확한 예외 규칙은 직접 더 넓은 범위의 규칙보다 앞에 배치해야 합니다.

  1. 명시적 예외를 먼저 배치: 특정 도메인을 차단하거나 업무용 도메인을 반드시 프록시로 보내는 경우입니다.
  2. 로컬 접속 규칙 배치: 사설 주소를 직접 연결해 로컬 네트워크 기기 접속에 미치는 영향을 줄입니다.
  3. 분류별 트래픽 분기 배치: geosite, geoip 등의 분류로 대부분의 연결을 처리합니다.
  4. 최종 기본 규칙 배치: 나머지 TCP 및 UDP 연결을 어디로 보낼지 명시합니다.

다음은 완전한 routing 조각이지만, 기존의 인바운드, 아웃바운드 등 설정과 합쳐야 합니다. 예시 텔레메트리 도메인을 먼저 차단하고, 로컬 네트워크와 cn 분류는 직접 연결로 보내며, 나머지 트래픽은 프록시로 보냅니다. 필요 없는 규칙을 삭제할 때도 JSON 쉼표 위치가 올바른지 확인하세요.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": ["full:telemetry.example.com"],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["geosite:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": ["geoip:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

어떤 규칙에도 매칭되지 않으면 일반적으로 proxy라는 이름의 아웃바운드가 아니라 아웃바운드 목록의 첫 번째 항목이 사용됩니다. 명시적인 기본 규칙은 설정을 이해하기 쉽게 해주지만 매칭 동작도 바꿉니다. 기본 규칙을 삭제하더라도 아웃바운드 순서는 확인해야 합니다. 프록시 연결 실패 후 자동 전환하려면 별도의 정책이 필요합니다. 일반 라우팅 규칙은 실패 시 다음 규칙으로 자동 재시도하지 않습니다.

5. domainStrategy로 조회 시점 결정하기

도메인 규칙은 도메인을 기준으로, IP 규칙은 주소를 기준으로 매칭합니다. 앱이 프록시 프로토콜로 도메인을 전달하면 코어가 대상 IP를 이미 가지고 있지 않을 수 있습니다. routing.domainStrategy는 라우팅 단계에서 매칭을 위해 도메인을 조회할지 결정합니다. DNS 서버 선택과 같은 설정이 아니며, 아웃바운드에 있는 같은 이름의 옵션과 혼동해서도 안 됩니다.

전략조회 시점주의 사항
AsIs라우팅 단계에서 매칭을 위해 도메인을 적극적으로 조회하지 않음도메인만 전달된 대상은 조회 결과를 이용해 IP 규칙에 매칭할 수 없음
IPIfNonMatch도메인이 어떤 규칙에도 매칭되지 않으면 조회를 시도한 뒤 다시 매칭먼저 매칭된 기본 규칙이 추가 조회를 막음
IPOnDemand매칭 중 IP가 필요한 규칙을 만나면 조회를 시도앞쪽의 IP 규칙이 DNS 조회를 늘리고 트래픽을 조기에 분기할 수 있음

특정 업무용 도메인을 반드시 프록시로 보내려면 해당 도메인의 full: 또는 domain: 규칙을 geoip:cn보다 앞에 두세요. IPOnDemand에서 IP 분류 규칙이 먼저 있으면 도메인을 조회한 결과가 cn 주소일 때 직접 연결로 이미 전송되어, 뒤에 있는 도메인 예외가 적용되지 않을 수 있습니다.

6. v2rayN에서 적용하고 검증하기

v2rayN은 데스크톱 클라이언트이며 실제 규칙은 선택한 코어가 실행합니다. 이 글은 V2Ray/Xray의 JSON 구조를 기준으로 합니다. 먼저 v2rayN 버전과 현재 코어를 기록한 다음 규칙을 수정하세요. 버전에 따라 편집 메뉴와 필드 이름이 달라질 수 있습니다. 코어 JSON 객체를 도메인 목록만 입력할 수 있는 칸에 그대로 붙여 넣으면 안 됩니다.

  1. 현재 설정을 백업하세요. 사용 중인 라우팅 설정과 기본 아웃바운드 설정을 보관하세요. 데스크톱 버전에서 흔히 사용하는 메뉴는 ‘설정’ → ‘라우팅 설정’입니다. 현재 버전에서 메뉴가 다르면 먼저 라우팅 설정 관리 메뉴를 찾으세요. 트래픽 분기를 시험하려고 구독 주소를 변경하지 마세요.
  2. 태그를 확인하세요. 설정 편집기 또는 생성된 코어 설정에서 outbounds의 tag를 확인합니다. 예제의 direct, proxy, block을 실제 태그에 맞추세요.
  3. 예외 규칙 하나만 추가하세요. 먼저 완전한 도메인 하나로 테스트하고 분류 규칙보다 앞에 배치합니다. 저장한 뒤 해당 라우팅 설정을 선택해 클라이언트가 설정을 다시 생성하도록 하고 코어를 재시작하세요.
  4. 시작 로그를 확인하세요. JSON 파싱 오류, 분류 누락, 아웃바운드 태그를 찾을 수 없음 등의 오류가 없는지 확인한 다음 연결을 테스트하세요.
  5. 새 연결로 검증하세요. 기존 페이지 연결을 닫고 요청을 다시 보냅니다. 접속 로그에 표시된 대상과 아웃바운드 태그를 확인하세요. 현재 로그에 관련 정보가 표시되지 않으면 로그 상세 수준을 일시적으로 높이세요.
  6. 단계적으로 확장하세요. 테스트에 성공한 뒤 geosite, geoip, 기본 규칙을 추가하세요. 규칙을 한 단계 추가할 때마다 되돌릴 수 있는 설정을 보관하세요.

테스트 대상은 직접 연결해야 하는 사이트, 프록시로 보내야 하는 사이트, 로컬 네트워크 기기 등 실제 대상 세 가지 이상을 준비하세요. 차단도 시험해야 한다면 제어 가능한 테스트 도메인을 하나 더 추가합니다. 규칙은 해당 코어에 진입한 연결에만 적용됩니다. 앱이 시스템 프록시를 우회하면 규칙이 올바르더라도 매칭 기록이 남지 않습니다. 시스템 프록시의 적용 범위는 시스템 프록시 사용 안내에서 확인할 수 있습니다.

7. 규칙이 적용되지 않을 때 자주 발생하는 문제 4가지

full 규칙을 추가했는데 왜 직접 연결되나요?

먼저 해당 규칙 위에 geosite:cn, geoip:cn 또는 전체 트래픽 규칙이 있어 연결을 먼저 처리하는지 확인하세요. 완전한 도메인 예외를 이 규칙들보다 앞에 옮기고 저장한 뒤 새 연결을 만드세요. 연결이 실제로 도메인을 전달하는지, 앱이 미리 조회한 IP를 전달하는지도 확인하세요.

geosite를 추가한 뒤 코어가 시작되지 않는 이유는 무엇인가요?

로그에 분류가 없거나 데이터 파일을 불러올 수 없다는 메시지가 있는지 확인하세요. 현재 데이터베이스에 지정한 분류가 있는지 확인하고 클라이언트에서 제공하는 규칙 데이터 업데이트 기능을 사용하세요. 분류 이름이 그럴듯하다는 이유만으로 사용하지 마세요. 먼저 추가한 항목을 삭제해 시작 상태를 복구한 다음 하나씩 확인하세요.

도메인과 IP를 한 규칙에 넣었더니 왜 매칭되지 않나요?

서로 다른 필드는 ‘그리고’ 조건이며, 도메인 조회 조건도 영향을 줄 수 있습니다. 둘 중 하나만 만족해도 되는 의도라면 규칙을 두 개로 나누고 같은 outboundTag를 사용하세요. 두 조건을 모두 충족해야 하는 경우에는 주소를 사용할 수 있는지와 domainStrategy가 어떻게 동작하는지 확인하세요.

규칙을 바꿨는데 브라우저가 왜 이전 경로를 계속 사용하나요?

라우팅은 일반적으로 새 연결이 만들어질 때 결정되며 이미 연결된 장기 연결은 아웃바운드를 다시 선택하지 않을 수 있습니다. 수정한 라우팅 설정이 현재 선택되어 있는지 확인하고 관련 앱의 연결을 종료하세요. 필요하면 코어를 재시작한 뒤 다시 시도하세요. 로그에 요청이 전혀 없다면 앱이 프록시 인바운드로 연결되고 있는지 확인하세요.

설정을 정리할 때는 설명할 수 있는 규칙만 간결하게 유지하세요. 정확한 예외, 로컬 주소와 분류, 명시적인 기본 규칙 순으로 배치합니다. 문제가 발생하면 규칙을 계속 추가하기보다 ‘연결이 코어에 들어왔는지, 대상이 도메인인지 IP인지, 어떤 규칙이 먼저 매칭됐는지, 태그가 존재하는지’ 순서로 확인하는 편이 원인을 찾기 쉽습니다.

클라이언트 다운로드