本文面向已经有可用代理出站、需要调整 DNS 策略的用户。先区分解析器选择与查询传输路径,再合并国内规则、远程 DoH 和直连出站配置,最后通过独立测试入口检查解析链路。示例采用 V2Ray 风格 JSON 片段,不替换订阅中的服务器配置,也不假定所有客户端使用相同内核。
一、DNS 分流分成解析器选择与查询路由
DNS 分流不是把两个服务器地址写进列表就结束。第一层决定某个域名交给哪个解析器,第二层决定发往解析器的连接走直连还是代理。只有两层都明确,才能判断境外域名的查询是否经过预期链路。加密 DNS 可以保护查询传输,但不能保证解析服务本身的返回结果始终正确。
内核 DNS 也不等于操作系统 DNS。应用通过 SOCKS 传入域名时,代理协议可能把域名交给服务器解析;应用先调用系统解析器拿到 IP 时,内核可能只看到 IP。仅修改配置中的 dns 对象,不会自动接管电脑或手机上全部程序的查询。
- 内核解析:路由需要 IP、直连出站需要解析,或 DNS 入站交给 DNS 出站处理时,才会涉及内置解析模块。
- 远端解析:目标域名随代理请求发送到服务器后,实际使用的解析器由服务端环境决定。
- 应用自带解析:浏览器的安全 DNS 可能独立发起 DoH 请求,不会直接使用这里的服务器列表。
二、配置前确认内核、规则文件与出站标签
v2rayN 是桌面配置管理客户端,实际行为取决于当前选用的内核。安卓端的 v2rayNG 使用 Xray 内核,v2flyNG 使用 V2Fly 内核。两者许多字段相近,但不能据此认定所有 DNS 选项、FakeDNS 行为和默认值完全一致。先记录内核名称及版本,再对照相应配置文档检查字段支持情况。
- 在 v2rayN 的「设置」→「参数设置」中检查与当前内核有关的选项;具体 DNS 编辑入口随客户端版本变化,以实际界面为准。
- 备份当前配置,查看生成配置中的
outbounds,记录代理与直连出站的真实tag。 - 确认运行目录中的
geosite.dat可读取且包含cn分类。只有使用 IP 分类时,才需要相应的geoip.dat规则。 - 先验证代理连接可用,再调整 DNS。代理出站自身不可达时,远程查询失败不能直接归因于解析器。
这些数字是配置中的端口约定,不是性能测量结果。下文把现有代理出站称为 proxy,直连出站称为 direct;如果实际标签不同,需要同步替换引用,不能只复制规则中的名称。
三、国内域名使用直连 DNS,其他查询使用远程 DoH
以下片段合并到现有配置顶层的 dns 字段。国内分类优先查询 223.5.5.5,没有命中该分类的查询使用 https://1.1.1.1/dns-query。这两个地址是具体的配置示例,不代表它们在每个网络环境中都可达,也不代表必须固定使用这组公共解析服务。
{
"dns": {
"queryStrategy": "UseIPv4",
"servers": [
{
"address": "223.5.5.5",
"port": 53,
"domains": [
"geosite:cn"
],
"skipFallback": true
},
{
"address": "https://1.1.1.1/dns-query"
}
]
}
}
domains是解析器的优先匹配条件。geosite:cn依赖规则文件中的分类,不等于按域名后缀简单判断,也不保证分类覆盖所有国内站点。skipFallback: true表示该服务器不参与未命中域名的通用回退,避免境外域名在回退阶段被发给这个直连解析器。- 此配置仍允许国内优先解析失败后尝试远程服务器,因此它不是“国内查询绝不出境”的严格隔离策略。需要严格隔离时,应另行核实内核的回退控制选项。
UseIPv4用于先缩小 IPv6 排障范围。它不等于系统禁用 IPv6;需要双栈时,应结合实际 IPv6 路由重新评估查询策略。
远程地址使用 IP 字面量,可以减少“为了连接 DoH,先解析 DoH 域名”的引导依赖,但仍需通过 TLS 证书验证。不要为解决连接报错而关闭证书验证。若改用域名形式的解析服务,应同时安排该服务域名的引导解析,避免再次依赖同一条尚未建立的 DNS 链路。
四、为 DNS 查询指定出站,避免默认路由改变链路
下面的规则片段采用 AsIs,先处理两个解析端点,再处理国内域名,最后将其余 TCP 与 UDP 连接交给代理。普通 https:// DoH 与带有本地直连语义的 https+local:// 不能混用理解:本例需要查询连接经过内核路由,因此使用前者。
{
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": ["223.5.5.5"],
"port": "53",
"network": "udp",
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["1.1.1.1"],
"port": "443",
"network": "tcp",
"outboundTag": "proxy"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
这是便于观察链路的基础策略,不包含局域网、企业内网或广告分类等规则。合并时应保留已有的必要规则,并检查顺序:规则通常按顺序匹配,放在末尾的兜底项不能提前遮住解析端点规则。上面的 IP 与端口规则还会匹配访问同一端点的其他连接,并非只识别 DNS 模块产生的流量。
对于直连出站,还需要检查 Freedom 的域名策略。下面是已有直连出站应具有的结构;应修改对应项,而不是添加第二个同名标签。UseIP 使该出站通过内置 DNS 取得目标 IP,否则默认行为可能继续依赖系统解析。
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIP"
}
}
结论:分别验证解析去向与连接去向
先确认国内直连出站确实调用内置 DNS,再确认远程 DoH 连接匹配到代理。仅看到网页能打开,不能证明 DNS 分流已经生效;代理请求携带域名时,目标解析仍可能发生在服务端。
五、用独立 DNS 入口验证,不把浏览器缓存当结果
为了直接测试内置解析模块,可以在现有 inbounds 与 outbounds 数组中分别追加下列对象。入站只绑定 127.0.0.1,不要改成对外监听地址。该入口用于本机排障,不会自动修改系统 DNS,也不会自动接管浏览器查询。
{
"tag": "dns-in",
"listen": "127.0.0.1",
"port": 1053,
"protocol": "dokodemo-door",
"settings": {
"address": "1.1.1.1",
"port": 53,
"network": "tcp,udp"
}
}
{
"tag": "dns-out",
"protocol": "dns",
"settings": {}
}
再把下面这条规则放到前文 routing.rules 的最前面,让测试请求进入 DNS 出站,而不是被末尾的代理兜底规则接走。DNS 出站对 A、AAAA 查询调用内置解析模块;其他记录类型的处理与转发行为应单独验证,不要用一次 TXT 查询代替本例的地址记录测试。
{
"type": "field",
"inboundTag": ["dns-in"],
"outboundTag": "dns-out"
}
- 重启内核,先检查配置加载日志,排除端口占用、未知字段和规则文件读取失败。
- 在安装了
dig的环境执行下列命令,分别触发国内分类与远程解析路径。 - 结合 DNS 调试日志与出站访问日志,确认两个解析端点实际使用的标签。排障期间可临时提高日志级别,完成后恢复。
- 每次只改一项设置。重复查询可能命中缓存;必要时重启内核并清理应用或系统缓存,再对照结果。
dig @127.0.0.1 -p 1053 www.baidu.com A
dig @127.0.0.1 -p 1053 www.example.com A
测试域名是否命中分类,仍以当前规则文件为准。解析结果不同不一定表示污染,CDN 调度、解析服务位置和缓存状态都可能改变答案。应观察查询是否发给预期解析器、是否出现超时,以及最终目标连接是否成功,而不是仅比较两次返回的 IP。
六、FakeDNS、缓存与路由解析策略的边界
FakeDNS 返回的是供内核映射使用的合成地址,不是目标站点的真实地址。它主要解决流量进入代理后保留或恢复域名信息的问题,不能代替真实解析服务,也不能修复不可达的代理服务器。开启前应确认当前内核、流量接管方式和域名恢复链路均支持相应配置。
| 设置或机制 | 实际作用 | 常见误判 |
|---|---|---|
| DNS queryStrategy | 控制内置解析模块查询或使用的地址族。 | 设成 IPv4 后,误以为所有应用都停止发起 IPv6 流量。 |
| routing.domainStrategy | 控制路由匹配时是否为域名取得 IP。 | 把 AsIs 理解为整个内核永远不解析域名。 |
| Freedom domainStrategy | 控制直连出站建立连接时如何处理域名。 | 只改 DNS 列表,却仍让直连出站依赖系统解析。 |
| FakeDNS | 维护域名与合成地址的映射,需要后续流量回到可恢复映射的内核。 | 只开启合成应答,未保证对应连接也被接管。 |
| DNS 缓存 | 复用此前取得的解析结果,减少重复查询。 | 修改配置后仍看到旧结果,就认定新配置未被加载。 |
IPIfNonMatch 会在域名规则未命中时尝试解析,再继续 IP 规则匹配;IPOnDemand 会在匹配需要 IP 的规则时触发解析。两者都可能增加本地查询。若配置里已经有必然命中的兜底规则,不要想当然地认为每个域名都会进入 IP 解析阶段。
- 先使用普通 DNS 与明确的域名规则验证基础链路,再增加 FakeDNS,避免同时引入地址映射与解析回退两个变量。
- 修改规则文件后,按客户端行为重启或重新加载内核;仅更新文件不等于运行中的规则已切换。
- 浏览器安全 DNS、系统 DNS 缓存与内核 DNS 缓存分别排查,清理其中一层不会自动清空其他层。
七、DNS 分流常见问题与排查顺序
写了远程 DNS,为什么浏览器仍请求本地解析器?
先确认查询是否进入内核。使用上文的 1053 端口测试入口单独验证,再检查浏览器安全 DNS 和系统代理行为。普通系统代理主要处理应用连接,不等于接管操作系统的 UDP 53 查询。
国内网站能打开,境外域名解析一直超时怎么办?
检查 1.1.1.1:443 是否匹配 proxy,确认该标签存在且代理连接正常。随后检查 TLS 错误和系统时间。若代理服务器地址本身是域名,还要排除它的引导解析依赖远程 DoH 所造成的循环。
更新订阅后,刚写的 DNS 配置怎么不见了?
检查改动是否写在客户端临时生成的运行配置中。生成文件可能在切换节点或重启时被覆盖。应使用当前版本提供的 DNS 设置或自定义配置入口保存,再重新查看生成结果,确认字段及标签确实保留。
开启 FakeDNS 后部分程序完全连不上,先改哪里?
先恢复普通解析并重启内核,清理相关应用缓存。确认恢复后,再检查合成地址对应的连接是否回到同一内核,以及入站域名恢复设置是否匹配当前内核要求。不要让拿到合成地址的程序绕过接管直接连接。
最终验收应保留三项记录:当前内核与配置来源、两个解析端点对应的出站标签、独立测试入口的查询日志。这样才能把问题定位到解析器选择、查询传输或目标连接阶段,而不是反复更换公共 DNS 地址。