本文适合已能连接节点、准备调整分流规则的用户。先确认内核拿到的是域名还是 IP,再选择匹配语法、排列规则,并通过日志验证出口。文中的 JSON 是内核配置片段,不是订阅内容;理解这些差别后,可以定位“规则已添加却没生效”“私网流量误走代理”和“分类规则加载失败”等问题。
一、路由规则如何决定出口
v2rayN 是客户端界面,V2Ray 或 Xray 内核负责实际匹配与转发。VMess、VLESS 是连接节点时使用的协议,不决定某个网站必须走哪个出口。路由位于连接处理过程中,依据目标域名、目标 IP、端口及入站标签等信息,选择一个已有的出站。
routing.rules 从上到下检查,第一条满足条件的规则决定出口,不会继续寻找“更精确”的规则。没有规则命中时,通常使用 outbounds 数组的第一项;因此默认出口也必须检查,不能只看规则末尾。
- 同一字段的多个值通常是“或”:
domain数组中任意一项匹配,域名条件就成立。 - 同一条规则的不同条件通常是“且”:同时填写
domain与port,需要域名和端口都满足。 - 不同规则之间按顺序判断:精确例外应放在宽泛分类之前,兜底规则放在最后。
- 出口名称必须真实存在:
outboundTag需要对应某个出站的tag,不是可以随意填写的说明文字。
二、domain、full 与 regexp 的匹配边界
domain 既是规则中的字段名,也可以是字段值的前缀,两者不是一回事。字段负责容纳域名条件,前缀负责规定如何匹配。需要覆盖主域名及所有子域名时,优先使用 domain:;只允许一个完整主机名时,使用 full:。
| 写法 | 匹配行为 | 边界示例 |
|---|---|---|
example.com | 不带前缀时按子串匹配 | 也可能匹配 notexample.com |
domain:example.com | 匹配主域名及其子域名 | 匹配 img.example.com,不匹配 notexample.com |
full:api.example.com | 匹配完整域名 | 不匹配 img.api.example.com |
regexp:^api[0-9]+\\.example\\.com$ | 正则表达式;此处展示 JSON 字符串内的写法 | 匹配 api12.example.com,不匹配 api.example.com |
域名规则不匹配网页 URL 的路径。若要处理 https://api.example.com/v1/status,目标域名是 api.example.com,不能把协议头、路径或查询参数一并写进域名字段。HTTPS 路径也不是普通路由规则可直接识别的条件。
{
"type": "field",
"domain": [
"full:api.example.com",
"domain:static.example.net",
"regexp:^edge[0-9]+\\.example\\.org$"
],
"port": "443",
"outboundTag": "proxy"
}
这条规则表示:三个域名条件满足任意一个,并且目标端口为 443,才走 proxy。正则中的点号需要转义;在 JSON 字符串里,一个反斜杠还要再转义,所以写成 \\.。若在客户端的纯文本域名输入框中填写,通常只需要 \.,不要把两种输入环境混用。
三、ip、CIDR 与 geoip 的适用场景
ip 字段处理目标 IP,可以填写单个地址、CIDR 网段或 geoip: 分类。它判断的是这次请求的目标地址,不是电脑本身的网卡地址,也不是节点服务器的地址。应用直接访问 IP 时,即使不进行域名解析,仍然可以命中 IP 规则。
显式网段规则
- 单个地址
192.168.1.10- IPv4 网段
192.168.0.0/16- IPv6 网段
fc00::/7- 数据依赖
- 不依赖地理分类文件
适合明确知道边界的局域网或固定服务网段。
geoip 分类规则
- 私有地址类
geoip:private- 地区地址类
geoip:cn- 常见数据文件
geoip.dat- 维护重点
- 分类存在且数据可读取
分类范围由所用数据集决定,不等同于实时网络位置。
{
"type": "field",
"ip": [
"127.0.0.0/8",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"::1/128",
"fc00::/7"
],
"outboundTag": "direct"
}
上述片段展示显式直连网段,并不是完整的特殊用途地址清单。若采用 geoip:private,应以当前数据集收录范围为准。对于公司内网,最好把实际使用的网段单独写明,避免仅凭“私网分类应该包含”作判断。
四、geosite 分类引用与数据文件
geosite: 写在 domain 数组中,用来引用域名集合;geoip: 则写在 ip 数组中。两者不是可以互换的前缀。geosite:cn 表示引用数据集中名为 cn 的集合,不能简单理解为所有以 .cn 结尾的域名。
{
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
}
- 先确认集合存在:同名数据文件可能来自不同维护来源,分类名称、内容及属性不一定一致。
- 区分两类加载失败:找不到
geosite.dat是文件或资源路径问题;找不到指定分类则是集合名称或数据版本问题。 - 更新后重新验证:集合内容变化可能改变命中结果,更新成功不代表原有分流行为完全不变。
- 按需使用属性筛选:例如
geosite:google@cn只有在所用数据集为对应条目提供该属性时才有预期意义,不能凭名称推断。
若内核在加载配置时立即退出,应先查日志中的资源加载错误,而不是反复切换节点。分类规则尚未成功加载时,连接速度测试无法证明路由配置正确。暂时移除有问题的分类引用、保留一条明确域名规则,有助于区分配置错误与网络故障。
五、domainStrategy 如何影响 IP 规则
routing.domainStrategy 控制路由判断时是否为域名目标解析 IP,不直接等同于最终出站的 DNS 策略。它也不会凭空恢复应用已经丢失的域名:如果应用提交的只有 IP,想使用域名规则还需要考虑入站嗅探等条件,而且嗅探并非对所有流量都有效。
| 策略 | 域名目标的处理 | 常见影响 |
|---|---|---|
AsIs | 不为路由匹配主动把域名解析成 IP | 域名目标通常不能仅靠 IP 规则分流;原本就是 IP 的目标仍可匹配 |
IPIfNonMatch | 先按现有目标信息匹配;未命中时再解析域名并重新匹配 | 首轮若已命中兜底规则,就不会触发这次回退解析 |
IPOnDemand | 匹配过程中遇到需要目标 IP 的条件时解析域名 | 靠前的 IP 规则可能先命中,影响后面的域名例外 |
一个常见误区是:设置了 IPIfNonMatch,又在规则末尾写了覆盖全部 TCP、UDP 的代理规则。由于这条兜底在首轮就能命中,域名目标不会走到“未命中后解析 IP”的步骤;前面的 geoip:cn 因而可能没有机会判断解析结果。
结论:先确定兜底方式,再选择解析策略
若需要用 IP 分类承接未匹配的域名,使用 IPIfNonMatch 时可依靠第一出站兜底,而不是加一条首轮必中的末尾规则;若选择 IPOnDemand,则把必须保留的域名例外放在宽泛 IP 分类之前。
这里的 DNS 结果会直接影响 IP 分类判断。遇到“同一个域名今天直连、明天代理”,应同时查看解析结果和分类数据,而不是立即认定规则顺序失效。更完整的 DNS 与路由字段说明可参照配置参考。
六、一份按优先级排列的路由示例
下面选用 IPOnDemand,明确展示“指定域名例外、私网直连、域名分类、IP 分类、最后代理”的顺序。它只是可并入现有配置的 routing 对象:前提是配置中已经有 proxy 和 direct 两个出站标签,并且相关分类数据可用。
{
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"domain": [
"full:api.example.com"
],
"outboundTag": "proxy"
},
{
"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"
}
]
}
}
示例中的 api.example.com 是用于解释规则的保留示例域名,不是可用性测试服务。它被放在第一条,因此即便之后的 IP 分类可能匹配,也会优先选择代理。实际使用时,把这一条改为需要固定出口的真实业务域名,或者直接删除。
- 保留原配置:在客户端中导出现有配置,记录当前启用的路由方案,避免修改失败后无法恢复。
- 检查真实标签:查看生成配置中
outbounds的tag,确认与示例一致;客户端可能使用不同的标签名。 - 仅合并路由对象:不要用这段内容覆盖完整配置,否则会丢失入站、节点出站、DNS 等必要部分。
- 在界面中保存并启用:v2rayN 的菜单名称会随版本变化,常见入口为「设置」→「路由设置」;新增规则后还需确认目标路由方案已启用。
- 重新建立测试连接:保存后按客户端提示重载或重启内核,并关闭旧网页连接再测试。已建立连接不一定重新执行路由匹配。
七、如何确认规则真正命中
网页能打开,只能说明连接成功,不能说明出口正确。验证分流应同时记录目标、协议、命中出口和测试时间。先用单个完整域名建立最小测试,再逐步加回分类规则,比一次修改十几条规则更容易定位问题。
- 确认流量进入内核:检查浏览器是否遵循系统代理。命令行测试可使用
curl --proxy socks5h://127.0.0.1:10808 https://example.com/ -I;其中10808必须替换为客户端实际 SOCKS 入站端口。 - 保留域名目标:上述命令使用
socks5h,把域名交给代理端处理;若应用先在本地解析再提交 IP,域名规则的测试前提就变了。 - 查看内核日志:关注目标地址和出站标签;日志格式因内核版本而异。访问日志未启用时,应按当前版本设置临时开启,而不是把“没有记录”当成没有流量。
- 建立三组对照:分别测试一个明确域名例外、一个可达的内网地址、一个普通公网域名,记录预期出口与实际出口。内网服务端口可按实际情况使用
80或443。 - 清理测试条件:关闭旧连接后重试;必要时重启测试应用。完成后恢复日常日志级别,避免长期积累详细访问记录。
为什么加了 full 规则,子域名还是不走代理?
full:example.com 只覆盖这个完整主机名。若需要同时覆盖 www.example.com,改用 domain:example.com,并把规则移到宽泛直连规则之前,再重新建立连接。
domain 和 ip 都填了,为什么更难命中?
同一条规则的两个字段不是二选一。若目标是“这些域名或这些 IP 都直连”,应拆成两条规则,并为两条分别设置同一个 outboundTag。
复制 geosite 分类后内核无法启动怎么办?
查看首条加载错误,确认 geosite.dat 的资源路径和分类名称。先移除该分类,使用 full: 规则验证内核能正常运行,再恢复有效的数据文件与分类。
安卓端能直接照搬桌面的整份配置吗?
v2rayNG 使用 Xray 内核,v2flyNG 使用 v2fly 内核;基础匹配语法相近,但出站标签、资源文件位置与导入方式由客户端决定。先核对所选内核支持的字段,再迁移路由片段,不要直接覆盖整份运行配置。
排查时优先遵循“目标信息、规则顺序、解析策略、数据文件、实际出口”的顺序。先证明一条精确规则能够生效,再扩大到域名集合和 IP 分类,通常比反复更换整套规则更可靠。