DNS 分流需要同时安排“谁来解析”和“查询走哪条出口”。本文适合已能正常连接节点、准备细化国内外域名规则的用户:先区分系统 DNS 与内核 DNS,再读懂服务器选择、路由策略和配置片段,最后按日志验证结果。普通系统代理场景不必直接启用 FakeDNS;先建立可复现的基础配置更容易定位问题。
1. DNS 分流的前提:请求必须进入内核
在 V2Ray 中填写 DNS 地址,不等于电脑上所有应用都改用这个地址。内置 DNS 主要处理内核需要执行的解析,例如路由按目标 IP 判断、部分出站的域名解析,以及配置了 DNS 入站转发的场景。应用自行发出的 DNS 查询,只有经过相应接管或转发路径,才会进入这套规则。
这条流程描述的是“应用把域名交给代理,并且路由需要解析”的一种路径。若域名规则已经决定代理出站,内核可能直接把域名交给远端,不在本地查询目标 IP。若应用先解析再把 IP 交给代理,内核收到的则可能已经不是域名。
| 接入方式 | 常见 DNS 行为 | 检查重点 |
|---|---|---|
| 浏览器使用 HTTP 代理 | 代理请求通常携带域名;浏览器也可能有独立解析、预取行为 | 安全 DNS、代理绕过列表 |
| 应用使用 SOCKS5 | 应用可提交域名,也可先在本机解析 | 是否启用远程域名解析 |
| 桌面 TUN 接管 | 取决于虚拟网卡路由与 DNS 接管配置 | DNS 是否真正进入接管路径 |
| 安卓 VPN 模式 | 客户端可接管流量;被排除的应用仍可能走原网络 | 分应用列表、私人 DNS 设置 |
v2rayN 是桌面客户端,v2rayNG 使用 Xray 内核,v2flyNG 使用 V2Fly 内核。三者不能仅凭界面中都出现“DNS”就互抄全部参数。本文代码采用 V2Ray/V2Fly 常见的传统 JSON 结构;实际能否加载,要以当前内核版本和客户端生成配置为准。
2. 内置 DNS 如何选择解析服务器
dns.servers 可以包含字符串地址,也可以包含带 domains 的服务器对象。域名命中某个对象的规则后,该服务器会成为优先查询对象;多个对象同时命中时,还要考虑它们在列表中的顺序。不能把整个数组简单理解成“第一项永远主用,第二项永远备用”。
- 检查静态映射与缓存。 配置中的
dns.hosts和已有缓存可能直接影响结果,因此更换服务器后不一定立即出现新的网络查询。 - 选择域名匹配的服务器。 例如
geosite:cn指向一组规则库中的域名,不是依据域名后缀临时判断所在地。 - 处理失败与回退。 优先服务器未获得可用结果时,在允许回退的配置下,再尝试可参与回退的服务器。被标记为
skipFallback: true的服务器不会作为普通回退候选。 - 返回解析结果。 结果还可能受到查询地址族、
expectIPs过滤和版本行为影响;最终是否重试,应结合该版本文档与日志判断。
expectIPs 可以筛选解析返回的地址范围,但它不是结果真实性验证机制。共享 CDN、跨境部署和规则库分类差异都可能导致合法结果被过滤。初次部署建议先不加,等查询路径稳定后再单独测试。
3. 国内外分开解析:DNS 与出口一起配置
下面给出一段用于合并的配置片段:国内分类优先查询 223.5.5.5,其他域名使用 https://1.1.1.1/dns-query。后者通过普通 DoH 地址形式接入内核路由,并用目标 IP 规则选择代理出口。它不是可直接启动的完整配置,也不包含节点信息。
{
"dns": {
"servers": [
{
"address": "223.5.5.5",
"domains": [
"geosite:cn"
],
"skipFallback": true
},
{
"address": "https://1.1.1.1/dns-query"
}
]
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"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",
"domain": [
"geosite:geolocation-!cn"
],
"outboundTag": "proxy"
},
{
"type": "field",
"ip": [
"geoip:cn"
],
"outboundTag": "direct"
}
]
}
}
- 先确认出站标记。 这里的
direct和proxy必须对应已有outbounds的tag。直连出站通常使用freedom;代理出站则复用已验证可用的节点。 - 核对默认出口。 传统配置中,未匹配规则的连接通常使用第一个出站。本片段没有定义它,需在现有配置中明确默认出口,不能假设未分类目标一定走代理。
- 保留已有规则。 合并到客户端配置时,应保留局域网、阻断和必要的系统规则,并检查顺序。路由首个命中的规则生效。
- 准备规则文件。
geosite:cn、geosite:geolocation-!cn和geoip:cn依赖对应规则数据。分类缺失或文件不可读时,先修复加载错误。
结论:先验证解析请求出口,再调整域名分类
若日志中 DoH 连接仍走直连,先修正 1.1.1.1:443 的路由与出站标记。单纯把 DNS 地址换成加密地址,不能替代出口配置,也不能解决代理节点本身不可达的问题。
示例的 IP 规则也会匹配其他发往相同地址与端口的连接,并非只识别 DNS。复杂配置可在内核支持的情况下使用 DNS 查询标记进一步区分。不要把普通 https:// 与带本地处理语义的 https+local:// 地址直接互换,后者的路由行为不同。
4. domainStrategy:何时触发解析,何时保留域名
routing.domainStrategy 控制路由判断阶段如何使用 IP,不是“所有 DNS 查询走代理”的开关。尤其要区分路由模块的同名字段与 freedom 出站中的 domainStrategy:前者决定如何匹配规则,后者涉及直连出站如何处理目标域名,支持值不能混用。
| routing.domainStrategy | 路由阶段行为 | 适用思路 |
|---|---|---|
AsIs | 对域名目标不主动做路由解析 | 主要依靠域名规则,减少额外查询 |
IPIfNonMatch | 域名未匹配路由规则时,再解析后参与 IP 匹配 | 域名规则优先,IP 规则补充 |
IPOnDemand | 匹配过程中遇到需要 IP 的规则时触发解析 | 需要较早利用 IP 分类时使用 |
以上示例使用 IPIfNonMatch:明确属于国内或非国内分类的域名,先按域名规则分流;未分类目标才可能解析并交给 geoip:cn 判断。这也解释了为什么“打开国外网站却没看到本地 DNS 查询”不一定是配置失效。
- 想减少本地解析:先补齐可靠的域名规则,不要一开始就把策略改为更积极的解析模式。
- 发现规则误分流:检查命中的第一条规则,再核对解析结果,避免只改 DNS 服务器。
- 已经收到 IP 目标:这三个选项不会凭空还原原始域名;是否可恢复要看嗅探信息、FakeDNS 映射等条件。
5. FakeDNS:虚拟地址映射需要完整接管链路
FakeDNS 返回的是本地维护映射的虚拟 IP,而不是网站真实服务器地址。应用连接这个地址后,内核再根据映射恢复域名,用于路由或后续代理。它解决的是“应用先解析,代理只收到 IP”的信息丢失问题,不是把 DNS 请求自动加密。
- 确认 DNS 请求被接管。 应用查询没有进入 FakeDNS,就不会生成对应映射;仅在配置中添加地址池没有实际作用。
- 确认虚拟 IP 的流量回到内核。 桌面 TUN 或安卓 VPN 的路由要覆盖该地址池,不能把它送到物理网络。
- 确认域名恢复能力。 对应入站需要匹配内核支持的 FakeDNS 嗅探设置;常见相关字段为
sniffing.destOverride中的fakedns。 - 确认直连路径能得到真实地址。 恢复域名后,直连目标仍需要适当解析,不能把虚拟地址当真实服务器连接。
普通系统代理且应用能传递域名时,优先保留真实解析方案。确实需要 FakeDNS 时,先阅读对应客户端和内核的功能说明,一次只启用一个接管机制。不要同时修改 TUN、DNS 劫持、嗅探和路由策略,否则无法区分是哪一层造成断网。
6. 配置验证:先看加载,再看解析与路由
DNS 排障应先区分配置加载失败、查询超时、解析成功但连接失败。VMess 或 VLESS 节点不可用时,经该节点发送的 DoH 也会超时;反过来,DNS 能返回地址并不代表节点握手、TLS 或目标端口正常。
- 记录基线。 保存当前可用配置,记录客户端版本、实际内核及版本、系统代理或 VPN 模式,以及分应用排除项。更新订阅前后也要确认当前节点没有变化。
- 修改后重启内核。 在客户端 DNS 或自定义配置入口保存后,查看启动日志。若出现未知字段、规则数据加载失败或找不到出站标记,先修复这些错误,不继续测网页。
- 临时增加日志细节。 在客户端提供的日志设置中临时选择调试级别,观察目标域名、DNS 连接地址和出站标记。完成测试后恢复常用级别,并在分享前移除节点地址与访问记录。
- 分别测试分类。 选择一个已确认在国内规则内的域名,以及一个已确认在非国内分类内的域名;再测试一个未分类域名。每类连续访问 3 次,留意首次查询与缓存命中的差异。
- 最后排除缓存。 重启应用或内核后复测,必要时清理系统 DNS 缓存。不要每次同时更换解析器、节点和规则文件。
ipconfig /flushdns
nslookup www.baidu.com 223.5.5.5
以上是 Windows 的辅助检查命令:第一行清理系统 DNS 缓存;第二行直接询问指定服务器。第二行不经过本文的内置 DNS 选择流程,因此只能检查该服务器的基础可达性,不能证明分流成功。若查询失败,还要考虑本地网络是否限制直连 UDP 53。
改了 DNS,浏览器怎么还是得到旧地址?
先关闭并重新打开测试页面,再检查浏览器安全 DNS 是否独立工作。Windows 可执行 ipconfig /flushdns,随后重启客户端内核;内核缓存与系统缓存不是同一份。仍无变化时,确认应用是否绕过系统代理。
国内网站也绕到远端 DNS,是规则写反了吗?
先检查域名是否属于当前 geosite:cn 分类,再看优先服务器是否查询失败后发生回退。不要把 skipFallback: true 当成禁止回退;同时核对 DNS 连接的路由是否被更靠前的规则截走。
安卓 VPN 已连接,为什么只有几个应用解析异常?
检查 v2rayNG 或 v2flyNG 的分应用代理列表,并记录系统「设置」中的「私人 DNS」状态;厂商系统菜单名称可能不同。临时排除应用自身的加密 DNS 干扰后复测,确认原因后再恢复需要的设置。
DoH 请求超时,是不是应该直接关闭证书验证?
先确认系统时间、代理节点可达性,以及 1.1.1.1:443 是否命中代理出口。检查日志区分连接超时与证书错误;保持证书验证开启,不用降低 TLS 校验要求来掩盖路由问题。
最终目标不是让所有域名都由同一台服务器解析,而是让域名分类、查询出口和业务出口相互一致。防污染配置能降低不可信查询路径的影响,但不能保证规则分类永远准确,也不能替代连接日志、证书验证和定期维护。