本文适合需要在 v2rayN 中添加域名例外、调整直连与代理顺序的用户。先区分域名、IP 与数据集三类匹配对象,再用一段 routing 配置说明首条命中、DNS 补充解析和兜底出站之间的关系。示例采用 V2Ray 与 Xray 常见的经典 JSON 路由结构;客户端界面规则最终仍需转换为当前内核能识别的配置。
1. 路由规则的基本结构与匹配对象
系统代理负责把应用连接送进入站,路由负责在流量进入内核后选择出站。浏览器没有使用系统代理时,即使规则正确,也可能完全绕过这套判断。因此,排查自定义规则之前,应先确认应用确实通过客户端访问,而不是直接检查网站显示的出口地址。
经典配置在 routing.rules 数组中存放规则。每条规则的 type 通常为 field,匹配条件可以是 domain、ip、port 或 network,结果由 outboundTag 指定。标签是配置里的引用名称,不是内核内置的固定动作。
{
"type": "field",
"domain": [
"full:api.example.com",
"domain:example.net"
],
"port": "443",
"network": "tcp",
"outboundTag": "proxy"
}
这条规则要求目标域名命中数组中的任意一项,同时目标端口为 443、传输网络为 TCP。域名数组内部是“或”,不同条件字段之间是“且”。它不会接管同一域名的 UDP 443 连接,也不会接管 TCP 80。下面的三个数字都是配置含义示例,不是速度测试结果。
2. domain、full、regexp 与普通字符串怎么写
domain 首先是规则中的字段名;字段数组里的 domain: 则是匹配方式前缀,二者不要混为一谈。数组项只填写域名或对应表达式,不填写网址协议、路径和查询参数。需要区分同一站点的不同 URL 路径时,普通域名路由无法完成这种细分。
| 写法 | 匹配范围 | 示例判断 |
|---|---|---|
full:example.com | 完整域名精确匹配 | 命中 example.com,不命中 www.example.com |
domain:example.com | 指定域名及其子域名 | 命中 example.com 和 a.example.com,不命中 notexample.com |
example.com | 普通字符串子串匹配 | 可能命中 notexample.com,范围通常比预期更宽 |
regexp:^api[0-9]+\\.example\\.com$ | 正则表达式匹配 | 命中 api1.example.com,不命中 api.example.com |
表格中的正则按 JSON 字符串形式展示。正则本身要用 \. 表示字面量句点,而 JSON 还要转义反斜杠,因此在配置文件中写成 \\.。如果是在客户端的普通文本输入框里填写表达式,通常输入单层反斜杠;不要把 JSON 转义形式机械复制到所有界面。
{
"type": "field",
"domain": [
"full:example.com",
"domain:example.net",
"regexp:^api[0-9]+\\.example\\.com$"
],
"outboundTag": "proxy"
}
结论:域名例外先用 full 或 domain
只处理一个主机名时用 full:,处理整个域及其子域时用 domain:。仅在主机名有明确变化规律时使用正则,并加好首尾锚点,避免把无关域名一并纳入。
3. ip、geoip 与 geosite 的区别
ip 字段用于目标地址匹配,可填写单个 IP、CIDR 网段,或 geoip: 数据集引用。geosite: 则写在 domain 数组中,表示按域名集合匹配。两类集合的成员不同,不存在“命中 geosite 就一定命中同名 geoip”的保证。
{
"type": "field",
"ip": [
"192.168.0.0/16",
"10.0.0.0/8",
"geoip:private"
],
"outboundTag": "direct"
}
上例先展示 CIDR 的具体写法,再展示私有地址集合;二者会有范围重叠,实际配置通常保留符合需求的一种即可。IPv6 单地址可使用 /128。不要只覆盖 IPv4 后就认定所有局域网连接都已处理,双栈网络还需要检查 IPv6 目的地址。
geosite:cn:引用数据文件中名为 cn 的域名集合,不等于仅匹配以 .cn 结尾的域名。geoip:cn:按地址数据库判断目标 IP 的归属范围,不代表网站内容语言,也不代表访问者所在地。geoip:private:引用私有地址等本地用途地址集合,具体覆盖范围以实际数据文件为准。- 数据依赖:经典数据集写法通常依赖内核可读取的
geosite.dat与geoip.dat。集合名称必须真实存在,不能自行猜测分类名。
同一域名可能使用多个地区的 CDN 地址,DNS 返回值变化后,IP 类规则的结果也可能随之变化。希望某个业务始终走指定出站时,应优先添加明确的域名例外,而不是长期绑定某次查询到的单个 CDN 地址。
4. 生效优先级:按顺序首条命中,不按精确度排序
在一次规则扫描中,内核按 rules 数组从上到下检查,命中后就选择该规则指定的出站。它不会因为后面的 full: 更精确而自动覆盖前面的 geosite:,也不会按照网段长短重新排序。所谓“例外优先”,是配置者主动把例外移到前面。
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["full:api.example.com"],
"outboundTag": "proxy"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:cn"],
"outboundTag": "direct"
}
]
}
}
这里将单域名例外放在域名集合之前。若同一连接能命中第二条,第三条便不会再参与竞争。但第一条私有 IP 规则是否能在初次扫描中匹配,还取决于目标是否已是 IP、当前域名策略是否触发解析;不能把“排在最上面”理解为一定先完成 DNS 查询。
- 目标为
api.example.com且入站保留域名时,第二条可直接选择proxy。 - 其他域名若命中
geosite:cn,第三条选择direct,不必等到 IP 补充匹配。 - 域名阶段全部未命中时,
IPIfNonMatch才尝试解析,并用取得的 IP 重新参与规则判断。 - 仍未命中时,经典配置会使用
outbounds数组中的第一个出站;它不一定名叫proxy。
5. domainStrategy 如何改变 DNS 与分流结果
routing.domainStrategy 控制路由匹配是否需要把目标域名解析为 IP。它不等于系统 DNS 设置,也不等于直连出站自身的同名策略。即使名字相似,所在配置层级不同,作用阶段也不同。
AsIs
路由阶段不为域名主动补做 IP 解析;目标原本就是 IP 时,IP 规则仍然可以匹配。连接最终是否需要解析,由后续出站等环节决定。
适合:规则以域名为主,希望路由决策不引入额外 DNS 查询的配置。
IPIfNonMatch
推荐先用已有目标信息匹配;没有任何规则命中时,再尝试解析域名,并让 IP 规则参与后续判断。需要避免过早命中的全量兜底规则。
适合:本文这种域名例外优先、IP 归属作为补充的分流结构。
IPOnDemand
匹配过程中遇到需要 IP 信息的规则时,按需触发解析。若靠前的 IP 规则命中,就可能先于后面的域名例外选定出站。
适合:明确要求 IP 规则尽早参与,并能控制 DNS 结果与规则顺序的配置。
例如,第一条是 geoip:private,第二条是某域名的代理例外。如果该域名解析到私有地址,IPOnDemand 可能让第一条先命中;而在 IPIfNonMatch 下,已能匹配第二条时就不需要等待补充解析。调整策略后,不能只验证网站是否打开,还应检查实际命中的出站。
- DNS 结果包含多个地址时,IP 类匹配应按内核对解析结果的处理理解,不能只拿命令行显示的第一个地址推断。
- 应用直接提交 IP 时,域名规则通常缺少匹配依据。嗅探在部分协议中可能恢复目标域名,但不能保证覆盖所有连接。
- 新增“拦截所有 UDP 53”并不能等价阻断所有 DNS;加密 DNS 可能使用其他端口与传输方式。
6. 在 v2rayN 中添加并验证自定义规则
以下以 v2rayN 7.x 桌面版常见界面为参照;不同小版本的按钮位置可能调整,规则字段应以当前窗口为准。界面维护的规则与完整 JSON 配置不是同一种输入格式,不要把整段 routing 对象粘贴进单个“域名”输入框。
-
确认内核
打开「设置」→「参数设置」,查看 Core 类型相关设置及当前配置采用的内核;启动后再核对日志中的内核名称。本文语法用于 V2Ray、Xray 经典路由配置,其他格式需要转换。
-
打开路由
进入「设置」→「路由设置」,先保留当前方案的备份,再编辑准备启用的规则集。确认编辑对象就是主界面当前选用的路由,而非一个未启用的副本。
-
添加例外
在规则编辑窗口选择目标出站,在域名项填入
full:api.example.com或实际需要处理的域名。先不加端口和网络限制,验证通过后再逐步收紧条件。 -
调整顺序
将例外放到可能覆盖它的域名集合规则之前,保存并选用该路由方案。客户端通常会重载相关配置;若日志没有反映变更,可重新启动服务后再测。
-
复查连接
关闭原有测试标签页并新建连接,查看连接日志中的目标与出站标签。需要更详细记录时,可在「设置」→「参数设置」中临时提高日志级别,完成后恢复常用级别。
路由调整通常针对新连接生效,浏览器连接复用和长连接可能继续使用原出站。一次刷新不足以证明新规则未生效。还应同时测试主域、子域和直接 IP 三类目标,避免只验证首页,而页面资源实际走了其他域名。
| 测试项目 | 观察内容 | 不符合预期时检查 |
|---|---|---|
| 精确域名 | 完整主机名是否选择指定标签 | 前置规则、实际启用的路由方案 |
| 子域名 | full 与 domain 的覆盖差异 | 是否误用普通字符串或漏掉子域 |
| 直接 IP | IP 规则是否独立生效 | CIDR 写法、IPv4 与 IPv6 地址族 |
| 未命中目标 | 是否进入计划中的默认出站 | 首个出站、全量兜底规则、解析策略 |
7. 自定义路由常见问题
把 full 规则放最后,为什么还是走直连?
更精确不代表优先级更高。打开「设置」→「路由设置」,把该规则移到可能命中的 geosite 或普通域名规则之前,保存后建立新连接,再观察出站标签。
写了 geoip:cn,域名访问却没有按地区分流?
先检查 routing.domainStrategy。若是 AsIs,路由不会主动解析域名供 IP 规则使用;若是 IPIfNonMatch,检查前面是否已有域名命中,或末尾是否存在提前结束匹配的全量规则。
添加 geosite 后内核启动报错怎么办?
先撤回新加项恢复连接,再查看启动日志。重点核对数据文件是否能被内核读取,以及所写分类是否存在。不要通过随意修改集合名反复试错;可先用单条 domain: 规则验证路由链路。
网站首页符合规则,登录和图片却不是同一出口?
查看这些请求的实际主机名。登录接口、静态资源和下载服务常使用不同域名;只写 full: 主域不会覆盖它们。属于同一受控域时可改用 domain:,独立域名则分别添加,避免直接扩大为模糊关键词。
切换内核后,原来的规则能直接沿用吗?
先确认目标内核接受的配置格式、数据集与出站标签,再逐条验证。V2Ray 与 Xray 有共同的经典字段,但客户端生成配置的方式和扩展能力可能不同;成功导入只说明配置被接收,不代表所有连接都按原路径出站。