跳到正文

V2Ray 自定义路由规则写法:domain、ip、geosite 匹配与优先级

拆解 domain、full、regexp、geosite、geoip 等匹配写法,说明规则自上而下的命中顺序,附多段可直接改写的规则示例。

本文速览

适合已经导入订阅、准备调整 v2rayN 分流规则的用户。先区分域名与 IP 匹配,再按“明确例外、分类规则、最终兜底”的顺序编排。本文示例采用 V2Ray/Xray 的 field 路由结构,展示可改写的 JSON 片段;应用前要核对实际内核、出站标签和规则数据库,不能把片段当作完整客户端配置直接运行。

一、先读懂一条路由规则

路由不是订阅节点列表。订阅提供服务器连接参数;路由决定某条连接交给哪个出站。更换 VMess 或 VLESS 节点,不会自动修复写错的域名条件。下面三个标签约定为 direct、proxy、block,分别代表直连、代理和阻断,但这些名字必须在实际配置的出站中存在。

连接进入内核 提取目标信息 顺序匹配规则 选择出站标签 出站处理连接

最简单的规则只需要说明“匹配什么”和“交给谁”。以下对象把 example.com 及其子域交给代理出站。它是 routing.rules 数组里的一个元素,不是完整配置。本文所有 example.com 域名都用于说明语法,使用时替换成实际目标域名。

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

例如,把 domain 和 port: "443" 放进同一个对象,意思是域名符合并且目标端口为 443 才命中,不是满足其中一个就生效。需要“域名符合或者 IP 符合”时,通常应拆成两条规则,而不是把两个字段塞进同一条。

二、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 中的 \\. 解析后才是正则里的 \.;漏掉一层反斜杠会造成解析错误或语义变化。

三、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 分流会同时影响许多不同网站,通常要配合域名等条件使用。

四、优先级:先命中就停止

规则按数组顺序从上到下检查,命中一条就选择对应出站,不再继续寻找“更精确”的后续规则。完整域名不会天然压过前面的分类规则,长网段也不会自动压过先出现的短网段。精确例外必须主动放在宽泛规则之前。

  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 的出站。显式兜底便于阅读,但会改变匹配行为;删掉兜底也不能不检查出站顺序。对于代理失败后的自动切换,还需要另外的策略,普通路由规则不会自动跳到下一条重试。

五、domainStrategy 决定何时解析

域名规则看域名,IP 规则看地址。如果应用通过代理协议提交的是域名,内核不一定已经持有目标 IP。routing.domainStrategy 决定路由阶段是否为了匹配而解析域名,不能把它等同于 DNS 服务器选择,也不能与出站中的同名选项混为一谈。

策略解析时机需要注意
AsIs路由阶段不主动为匹配解析域名纯域名目标无法靠解析结果命中 IP 规则
IPIfNonMatch域名未命中任何规则后,再尝试解析并重新匹配提前命中的兜底会阻止这次补充解析
IPOnDemand匹配过程中遇到需要 IP 的规则时尝试解析前置 IP 规则可能增加 DNS 查询并提前分流

假设某个业务域名必须走代理,就应把它的 full: 或 domain: 规则放在 geoip:cn 之前。使用 IPOnDemand 时,如果 IP 分类在前,域名解析到 cn 地址后可能已经被送往直连,后面的域名例外便没有机会执行。

六、在 v2rayN 中应用与验证

v2rayN 是桌面客户端,实际规则由所选内核执行。本文针对 V2Ray/Xray 的 JSON 结构;先记录 v2rayN 版本和当前内核,再编辑规则。不同版本的编辑入口和字段名称可能调整,不能把核心 JSON 对象直接粘到只接受域名列表的输入框。

  1. 备份当前方案。保留正在使用的路由配置与默认出站设置。桌面版常见入口为「设置」→「路由设置」;若当前版本入口不同,先查找路由配置管理,不要改订阅地址来尝试分流。
  2. 核对标签。在配置编辑器或生成的核心配置中查看 outbounds 的 tag。将示例里的 direct、proxy、block 对应到实际标签。
  3. 只加一条例外。先用一个完整域名做测试,放到分类规则之前。保存后选中这套路由配置,让客户端重新生成配置并重启内核。
  4. 检查启动日志。确认没有 JSON 解析错误、缺失分类或找不到出站标签等错误,再进行连接测试。
  5. 新建连接验证。关闭旧页面连接,重新发起请求。结合访问日志中的目标和出站标签判断;若当前日志不显示这些信息,临时提高日志详细度。
  6. 逐步扩展。成功后再添加 geosite、geoip 与兜底规则,每增加一层都保留可回退的配置。

测试至少准备三类真实目标:应直连的站点、应代理的站点、局域网设备。需要阻断时,再补一个可控的测试域名。规则只影响进入该内核的连接;应用绕过系统代理时,即使规则写得正确也不会出现匹配记录。系统代理的接管范围可结合系统代理使用说明检查。

七、规则不生效时的四个常见问题

写了 full 规则,为什么还是走直连?

先查它上方是否已有 geosite:cn、geoip:cn 或全流量规则命中。把完整域名例外移到这些规则之前,保存并重新建立连接。再确认连接实际提交了域名,而不是应用预先解析后的 IP。

加上 geosite 后,内核为什么启动失败?

查看日志是否提示分类不存在或数据文件无法加载。确认当前数据库含有所写分类,并通过客户端提供的规则数据更新入口更新。不要仅凭分类名看起来合理就使用;先删去新增项恢复启动,再逐项核对。

域名和 IP 都写进一条规则,怎么反而匹配不到?

不同字段是“且”关系,还可能涉及域名解析条件。如果意图是二选一,拆成两条规则,并使用相同的 outboundTag。如果确实要求两者同时满足,再检查地址是否可用以及 domainStrategy 的行为。

改了规则,浏览器为什么还沿用旧路线?

路由一般在新连接建立时决定,已建立的长连接不一定重新选择出站。先确认当前选中的是修改后的路由,再关闭相关应用连接;必要时重启内核后重试。若日志中完全没有请求,检查应用是否进入代理入口。

整理配置时保留少量、可解释的规则:先精确例外,再本地地址和分类,最后明确兜底。遇到问题按“连接是否进入内核、目标是域名还是 IP、哪条先命中、标签是否存在”的顺序排查,比不断叠加规则更容易找到原因。

下载客户端