本文面向已经能够导入节点、启用系统代理,并希望在 v2rayN 或 Xray 配置中精确控制连接出口的用户。重点包括域名与 IP 规则语法、规则数组的扫描顺序、同一规则内部的组合逻辑、domainStrategy 的影响,以及从日志和生成配置定位分流问题的方法。
路由处理链与首条命中原则
V2Ray 与 Xray 的路由模块不负责建立节点连接,而是在请求进入内核后,根据目标域名、目标 IP、端口、网络类型和入站标签等信息选择出站。最终选择结果通常由 outboundTag 指向一个已定义的出站,例如 proxy、direct 或 block。
规则存放在 routing.rules 数组中,内核从第一条开始向下检查。某条规则满足全部条件后,扫描立即停止,后面的规则不再参与本次请求。因此,“更具体的规则在前、更宽泛的规则在后”是稳定配置的基础。
同一条规则中的不同字段通常是“并且”关系。例如一条规则同时写了 domain 和 port,目标必须同时符合域名条件和端口条件。一个字段内部的多个项目通常是“或者”关系,例如 domain 数组列出三个域名,命中其中任意一个即可满足该字段。
| 位置关系 | 判断方式 | 实际结果 |
|---|---|---|
| 不同规则之间 | 自上而下扫描 | 第一条完整命中的规则生效 |
| 同一规则的不同字段 | 同时满足 | domain 与 port 都匹配才生效 |
| 同一字段的多个值 | 任意一个匹配 | 数组内项目按“或者”处理 |
| 没有规则命中 | 使用默认出站 | 通常落到配置中的首个可用出站 |
domain:精确域名、子域名与关键词匹配
domain 字段处理目标主机名。常用前缀包括 full:、domain:、keyword:、regexp: 和 geosite:。前缀决定匹配范围,选择不当会造成规则覆盖过宽或根本无法命中。
full:example.com 只匹配完整主机名 example.com,不会把 www.example.com 视为同一个目标。domain:example.com 则匹配该域名及其子域名,适合把同一站点体系交给相同出站。
{
"type": "field",
"domain": [
"full:api.example.com",
"domain:static.example.net",
"keyword:media",
"regexp:^cdn-[0-9]+\\.example\\.org$"
],
"outboundTag": "proxy"
}
- full: 适合登录接口、更新接口等明确主机名,匹配范围最窄。
- domain: 适合主域名及全部下级子域名,是日常规则中更常用的形式。
- keyword: 只要目标域名包含指定字符串就可能命中,短关键词容易误伤无关域名。
- regexp: 适合结构固定但编号变化的域名,表达式复杂时会增加维护成本。
- geosite: 引用预先整理的域名分类集合,适合按服务类别或区域批量分流。
精确接口规则
- 字段
- domain
- 写法
- full:api.example.com
- 范围
- 单一完整主机名
- 出站
- proxy
用于覆盖范围明确、不能连带子域名的连接。
整站直连规则
- 字段
- domain
- 写法
- domain:example.cn
- 范围
- 主域名与子域名
- 出站
- direct
适合目标站点全部服务采用相同出口的场景。
如果精确域名需要作为分类规则的例外,应把精确规则放在前面。例如先把 full:download.example.com 指向直连,再把 domain:example.com 指向代理。顺序颠倒后,下载域名会提前被整站规则接收。
ip 与 geoip:地址段匹配和域名解析条件
ip 字段可以写单个地址、CIDR 地址段以及 geoip: 分类。单个 IPv4 地址可以写成 198.51.100.20,网段可写成 198.51.100.0/24。IPv6 地址段同样使用 CIDR 表示,例如 2001:db8:1200::/48。
geoip:private 常用于匹配局域网、回环和其他非公网地址。把这类地址放到直连规则前部,可以避免本地路由器管理页、局域网文件服务或本机接口被送往远端代理。
{
"type": "field",
"ip": [
"geoip:private",
"192.0.2.0/24",
"2001:db8:1200::/48"
],
"outboundTag": "direct"
}
IP 规则能否处理一个最初以域名形式发起的请求,还取决于 domainStrategy。目标只有域名而没有目标 IP 时,内核必须决定是否解析该域名,再把解析结果交给 ip 规则比较。
| domainStrategy | 解析行为 | 适用判断 |
|---|---|---|
| AsIs | 域名按原样参与路由,不主动为 IP 规则解析 | 主要依靠 domain 与 geosite 分流 |
| IPIfNonMatch | 域名规则未命中后,再解析 IP 并继续检查 | 域名规则优先,IP 分类作为补充 |
| IPOnDemand | 遇到需要目标 IP 的规则时按需解析 | 前部已有重要 IP 规则的配置 |
结论:先确定解析策略,再评价 IP 规则
目标以域名进入且配置使用 AsIs 时,后置 geoip 规则没有命中并不代表地址库失效。先检查 domainStrategy,再查看日志中的目标形式,能避免反复改动 CIDR 和规则顺序。
geosite 与 geoip 的边界
geosite 是域名集合,geoip 是 IP 地址集合。两者解决的是不同阶段的信息分类问题,不能互相替代。站点采用动态地址、共享云服务或频繁调整解析结果时,域名集合通常比固定 IP 段更适合表达服务归属。
一条 geosite:cn 规则依据目标域名是否存在于对应分类中作出判断;一条 geoip:cn 规则依据目标 IP 是否落入对应地址集合中作出判断。域名与服务器所在地并非必然一致,因此两条规则可能对同一连接给出不同分类结果。
geosite 域名集合
- 输入
- 目标域名
- 示例
- geosite:cn
- 依赖
- 域名数据文件
- 常见用途
- 按服务归属分流
目标地址变化时,域名规则仍可保持稳定表达。
geoip 地址集合
- 输入
- 目标 IP
- 示例
- geoip:private
- 依赖
- 地址数据文件
- 常见用途
- 局域网与区域地址分流
域名请求是否进入地址判断受 domainStrategy 控制。
数据文件需要与内核版本和配置能力相匹配。出现“failed to load geosite”或分类名称无法识别时,应先确认数据文件位于内核实际读取的目录,再确认分类名称存在。仅调整规则顺序无法修复数据文件缺失。
outboundTag 与完整规则组合
outboundTag 的值必须与 outbounds 数组中某个出站的 tag 完全一致,包含大小写差异也会被视为不同名称。规则写成 "outboundTag": "direct" 时,配置中必须存在标签为 direct 的出站。
典型顺序可以拆成四层:私有地址直连、精确例外、分类分流、兜底处理。阻断规则如果涉及特定域名或端口,应放在可能覆盖它的宽泛代理规则之前。
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"domainMatcher": "hybrid",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["full:updates.example.com"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:cn"],
"outboundTag": "direct"
}
]
}
}
- 第一条处理局域网与本机地址,避免内部服务进入代理链路。
- 第二条定义明确例外,使指定更新域名始终采用直连。
- 第三条按域名集合处理已分类站点,不需要等待 IP 分类。
- 第四条在域名规则未覆盖时,以解析后的地址集合补充判断。
- 未命中的请求继续使用配置默认路径,实际出口由完整出站结构决定。
结论:出站标签先固定,路由条件再扩展
先用三个清晰标签建立 proxy、direct、block 出站,再逐条增加规则。标签稳定后,日志中的路由结果更容易对应到实际连接,不必同时排查条件和出站定义。
如果配置使用负载均衡器,规则可能通过 balancerTag 指向均衡器,而不是直接指定单一出站。普通自定义分流优先使用 outboundTag,只有确实配置了选择器与均衡器时再引入 balancerTag,避免增加不必要的排查层级。
v2rayN 中的配置路径与验证步骤
在 v2rayN 7.x 中,可先进入「设置」→「路由设置」查看当前路由配置和预设规则。不同小版本的按钮位置可能有调整,但验证目标相同:确认当前启用的路由配置、规则排列顺序和最终生成的内核配置一致。
修改后不要只看浏览器是否能打开网页。浏览器缓存、DNS 缓存以及已有连接复用都可能掩盖结果。应重新启动内核,使用新的目标连接,并把日志级别临时调整为 info 或 debug 后观察路由记录。
- 在「设置」→「路由设置」确认当前选中的规则集,记录预期命中的规则位置。
- 检查规则中的
outboundTag,并与生成配置中outbounds[].tag逐字对照。 - 在「设置」→「参数设置」确认本地监听和日志相关选项,常见 SOCKS 端口为 10808,HTTP 端口为 10809。
- 保存配置并重启内核,关闭原有浏览器连接或换用新的测试域名。
- 查看日志里的目标域名、目标地址和出站标签,判断请求在哪一条规则停止扫描。
- 一次只移动或修改一条规则,复测后再处理下一处,避免多个变化互相干扰。
检查清单
1. 目标是域名还是 IP
2. domainStrategy 是否触发解析
3. 精确规则是否位于分类规则之前
4. outboundTag 是否存在且大小写一致
5. geosite 与 geoip 数据是否成功加载
6. 测试连接是否为修改后的新连接
规则不生效的常见定位问答
路由问题通常不是单一语法错误,而是目标形式、解析策略、排序和出站标签共同作用的结果。先确认日志里实际出现的目标,再对照规则条件,比直接扩大匹配范围更可靠。
写了 geoip:cn,域名还是走代理?
先检查 domainStrategy。使用 AsIs 时,域名请求不会仅为后置 IP 规则主动解析。可根据配置目标改为 IPIfNonMatch,并重新建立连接后查看日志。
精确域名规则为什么没有覆盖 geosite?
检查精确规则是否排在 geosite 规则前面,并确认使用的是 full:主机名。如果前面的宽泛规则已经命中,后面的精确规则不会继续执行。
同一规则同时写 domain 和 ip 会怎样?
两类条件需要同时满足。若目标域名符合 domain,但解析地址不在 ip 集合中,整条规则仍然不命中。需要表达“域名或 IP 任一命中”时,应拆成两条规则。
outboundTag 拼写正确,连接仍然失败?
继续检查对应出站是否能独立建立连接,以及标签大小写、节点参数和传输配置是否有效。路由命中只完成出口选择,不代表该出站连接一定成功。
修改规则后结果没有变化?
保存后重启内核,关闭已有长连接,并清理测试应用的连接复用状态。随后用未访问过的测试主机名发起新请求,再从最新日志确认出站标签。
最终配置应保持规则目的可读:一条规则处理一个明确意图,标签名称反映出口用途,例外规则紧邻其覆盖对象。规则数量增加后,清晰的排序和最小条件比堆叠关键词更容易长期维护。