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

逐条解释 domain 的 full、domain、keyword、regexp 前缀与 geosite、geoip 数据集用法,说明规则自上而下匹配的顺序,以及如何避免规则互相覆盖。

本文速览

本文适合已经导入节点、需要调整直连与代理分流的用户。先区分域名匹配与 IP 匹配,再用配置片段说明规则顺序、解析策略和默认出站。特别注意:关键词匹配通常直接写字符串,不能把说明中的 keyword 当作通用 JSON 前缀。文中使用示例域名,不包含可连接的代理节点。

一、路由先决定出站,不负责创建节点

V2Ray 路由读取连接的目标地址、端口、网络类型等信息,再把连接交给某个出站。它不负责把订阅转换成节点,也不会因为写了 outboundTag: "proxy" 就自动生成代理服务器。标签只是引用,必须能在当前配置的 outbounds 中找到对应的 tag。

入站接收连接读取目标信息顺序匹配规则选择出站标签建立目标连接

域名规则能否生效,还取决于内核是否拿到了域名。应用通过 SOCKS 传递域名时,内核可以直接匹配;应用先自行解析再提交 IP 时,域名信息可能已经丢失。流量嗅探可以从部分协议中识别主机名,但不是所有加密流量都能恢复域名,也不能把它当作 DNS 的替代品。

二、domain 的四种写法:精确、子域名、关键词与正则

domain 是一个字符串数组。同一数组中的多个条目是“或”关系,任意条目命中即可。下面以 example.com 为例区分边界;不要把完整网址、路径或查询参数放进域名条目,路由匹配的不是浏览器地址栏中的整条 URL。

写法匹配范围边界说明
full:example.com仅 example.com不含 www.example.com
domain:example.com根域及其子域不匹配 notexample.com
example域名中包含 example 的字符串可能同时命中 notexample.net
regexp:^api[0-9]+\.example\.com$api 后接数字的指定子域需在 JSON 中转义反斜杠
{
  "type": "field",
  "domain": [
    "full:login.example.com",
    "domain:static.example.com",
    "regexp:^api[0-9]+\\.example\\.com$"
  ],
  "outboundTag": "proxy"
}

上面的正则是 JSON 字符串,所以正则里的一个反斜杠要写成两个。^ 和 $ 限定首尾,避免只匹配域名的一小段。只需要整站分流时,优先使用 domain:,比宽泛的关键词和复杂正则更容易检查。

三、geosite 与 geoip:分类数据不是自动推断

geosite 引用域名分类,放在 domain 数组里;geoip 引用 IP 分类,放在 ip 数组里。两者依赖内核可读取的数据文件和其中实际存在的分类。写下分类名并不会触发在线搜索,也不会自动下载缺失的数据。

域名分类规则

规则字段
domain
示例条目
geosite:cn
常见数据文件
geosite.dat
匹配依据
数据集中列出的域名规则

分类内容由数据文件决定,不等同于服务器所在地。

IP 分类规则

规则字段
ip
示例条目
geoip:private
常见数据文件
geoip.dat
匹配依据
数据集收录的地址网段

示例分类必须在当前数据文件中存在,加载报错时先检查文件与分类名。

域名属于某个分类,不代表它所有 CDN 地址都属于相同的 IP 地区。反过来,某个 IP 被收录到地区分类,也不能说明使用该地址的所有域名都应该直连。需要明确控制的业务域名,应写成独立规则,放在宽泛分类之前。

四、ip、CIDR 与端口:同字段取或,不同字段取且

ip 可以填写单个地址、CIDR 网段或受支持的数据集引用。CIDR 的斜杠后数字是前缀长度,不是端口。下面三个数字是语法边界,用于核对输入,不是网络测速结果。

/32
IPv4 单地址前缀
/128
IPv6 单地址前缀
443
下例限制的目标端口
{
  "type": "field",
  "ip": [
    "192.168.0.0/16",
    "10.0.0.0/8",
    "fc00::/7"
  ],
  "port": "443",
  "network": "tcp",
  "outboundTag": "direct"
}

这条规则只让“目标 IP 属于三个网段之一,并且目标端口是 443,并且网络类型为 TCP”的连接直连。它不是把所有内网流量都直连;访问内网设备的 80 端口或 UDP 服务仍要继续匹配后续规则。

同一规则里再加入 domain,并不会变成“域名或 IP 任一符合即可”,而是新增必须同时满足的条件。尤其在目标最初只有域名、解析尚未触发时,这种组合容易与预期不一致。需要“指定域名直连,或者指定 IP 直连”,应拆成两条规则。

结论:先拆规则,再合并条件

把域名例外与网段例外分别写成单条规则,确认各自命中后,再考虑是否确实需要端口或网络类型的交集限制。

五、规则从上到下匹配,不按“越具体越优先”排序

在一次规则扫描中,先匹配的规则决定出站,后面的规则不再替它改判。内核不会自动把 full: 提到 geosite: 之前,也不会给更长的域名更高权重。具体例外、业务规则、宽泛分类、最终兜底,应由配置者明确排列。

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": ["full:login.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"
      }
    ]
  }
}

这是用于合并的 routing 片段,不是完整客户端配置。它要求已有 proxy 与 direct 出站,其中 direct 通常使用 freedom 协议。第一条让登录域名走代理,第二条让其余根域和子域直连。若交换两条规则,登录域名会先被第二条覆盖。

  1. 要求域名优先、未命中后再尝试 IP 规则:使用 IPIfNonMatch,并避免提前匹配所有流量的兜底规则。
  2. 需要扫描到 IP 规则时主动尝试解析:研究 IPOnDemand,同时评估新增 DNS 请求和等待时间。
  3. 不写全匹配兜底时:核对 outbounds 的第一项。未匹配任何规则的流量默认使用第一个出站,标签名本身没有默认魔法。

六、domainStrategy 与 DNS:先确认目标是什么

同一组规则可能在浏览器里正常,在另一个程序里却表现不同。关键不一定是规则被忽略,而是两个程序提交的目标不同:一个提交域名,另一个提交已经解析的 IP。路由解析策略只控制路由判断所需的解析行为,不保证应用、系统与内核采用相同 DNS。

策略触发方式检查重点
AsIs路由不为域名主动补充 IP原始目标为域名时,不能依赖 IP 分类分流
IPIfNonMatch域名在第一轮未匹配规则后尝试解析,再匹配过早的全匹配规则会阻止第二轮
IPOnDemand域名请求匹配到需要 IP 判断的规则时尝试解析IP 规则的位置和 DNS 可达性都会影响结果

更改路由后,已有的长连接通常不会重新选择出站。应关闭测试程序的旧连接,再发起新请求;必要时重启内核。若同时修改 DNS、嗅探与路由顺序,就很难确定是哪一项改变了结果。每轮只改一个变量,并保留可恢复的配置副本。

七、在客户端落地与排查规则未生效

v2rayN 是桌面客户端,v2rayNG 使用 Xray 内核,v2flyNG 使用 v2fly 内核。本文片段使用两类内核常见的原生路由字段,但不能据此推断所有扩展语法、数据文件和界面导入格式完全相同。客户端保存的规则条目与最终生成的内核 JSON 也可能不是同一种文件格式。

  1. 备份当前方案。在 v2rayN 的「设置」→「路由设置」中检查当前启用的路由方案;不同界面版本的入口文字可能略有变化。先复制方案,再添加一条明确的 full: 例外。
  2. 核对生成结果。检查实际运行配置中的 routing.rules 顺序、outbounds 标签,以及是否被全局代理或全局直连模式替换。
  3. 区分规则表单与完整配置。v2rayNG 的「设置」→「路由设置」可检查常用域名和 IP 分流项;这些表单不等同于原生 JSON 编辑器。复杂有序规则应采用当前版本明确支持的自定义配置方式。
  4. 重新建立连接。应用设置并重启服务,再查看运行日志;只刷新页面可能继续使用旧连接。日志级别若不足以显示路由细节,可临时提高,测试完恢复。

域名已经填了,为什么还是走代理?

先确认这条规则在代理兜底之前,再把它临时改成单一 full: 测试。检查内核收到的是域名还是 IP;只有 IP 时,单纯增加域名条目无法解决信息缺失。

加了 geosite 后服务启动失败怎么办?

先恢复上一份配置,在日志中定位具体分类名和文件路径。确认数据文件可读取、分类存在,再添加该条规则;不要连续更换多个分类名碰运气。

规则显示保存成功,怎么一点变化都没有?

检查当前启用的路由方案是否就是编辑的那份,并确认不是全局模式覆盖。重新启动内核后建立新连接,再核对实际配置中的出站标签,而不只看表单提示。

能不能把所有条件塞进一条规则?

只有需要条件同时成立时才这样写。域名、IP、端口和网络类型一起填写是交集;想表达多个独立例外,就拆成多条,并按明确例外优先的顺序排列。

最后用三个新连接验证方案:一个精确例外域名、一个普通子域名、一个已知内网 IP。分别记录目标形式、命中规则和出站标签。这样能把“语法能加载”“规则确实命中”“出站本身可连接”分开检查,避免把节点故障误判为路由失效。更多概念可查阅术语表,配置边界可对照进阶配置。

客户端下载v2rayN / v2rayNG