本文适合已经能够连接节点、准备调整 DNS 与路由规则的用户。示例以 Xray 内核的传统 JSON 配置为基线,区分解析器选择、解析结果筛选和连接出口三个环节,并提供可合并的配置片段与验证步骤。V2Fly 的字段支持应按实际内核版本核对,不能只凭客户端名称判断兼容性。
先区分解析与连接出口
DNS 分流决定“向哪个解析器询问域名”,路由分流决定“连接从哪个出站发送”。二者有关联,但不是同一个开关。给某个域名指定国内解析器,不等于该域名一定直连;给连接选择代理出站,也不等于应用此前的 DNS 查询已经经过代理。
这条流程对应本文使用的 routing.domainStrategy: "IPIfNonMatch":先尝试域名规则,未匹配时才为 IP 规则解析地址。若域名规则已经命中,路由阶段可能完全不查询内置 DNS;后续是否解析,取决于具体出站的处理方式。因此,不能把“没有看到 DNS 日志”直接判为配置未生效。
- 应用交给内核的是域名:域名规则可以直接匹配,内核也有机会执行内置解析。
- 应用交给内核的是 IP:原始域名可能已经丢失,单靠
geosite不能还原它。 - 应用自行使用加密 DNS:查询可能绕过内核的
dns配置,需要单独检查应用设置。 - 仅打开系统代理:通常只是让支持代理的应用使用代理入口,并不接管系统全部 DNS 流量。
servers、domains 与 expectIPs
dns.servers 是解析器列表,既可写服务器地址,也可写带条件的对象。对象中的 domains 用于优先匹配域名;expectIPs 用于检查该服务器返回的地址是否符合预期。前者选择查询对象,后者筛选结果,不能互相替代。
国内域名解析器
- address
223.5.5.5- domains
geosite:cn- expectIPs
geoip:cn- skipFallback
true
优先处理国内域名,并从其他域名的通用回退候选中排除。
通用回退解析器
- address
https://1.1.1.1/dns-query- 传输
- HTTPS
- domains
- 不限定
- 查询族
- 继承全局
UseIPv4
承接未命中专用规则或专用结果未通过筛选的查询。
skipFallback: true 的含义是“该服务器不参与通用回退”,不是“命中该服务器后禁止再回退”。如果国内域名的应答不符合 expectIPs,示例仍可尝试另一个回退解析器。把这两个语义混淆,会误判实际的查询去向。
geosite:cn 来自域名分类数据,geoip:cn 来自 IP 分类数据。它们不是实时地理位置服务,也不是按网页显示语言判断地区。国内服务使用境外地址、跨区域 CDN 或分类数据滞后时,严格的地址预期可能过滤掉有效结果。
- 单个域名规则可用
full:example.com精确匹配。 domain:example.com可匹配该域名及其子域名。- 引用
geosite:cn和geoip:cn前,应确认当前运行内核能够读取对应数据文件。 expectIPs是分类筛选,不是应答真实性证明,不能仅凭返回地址属于某地区就认定结果正确。
合并 DNS 与路由片段
下面的 JSON 不是完整节点配置。它假定现有 outbounds 中已经存在 direct 和 proxy 两个标签,分别对应直连出站与已验证可用的代理出站。合并时更新现有的 dns 和 routing,不要在同一个对象里重复声明这些键。
{
"dns": {
"queryStrategy": "UseIPv4",
"servers": [
{
"address": "223.5.5.5",
"domains": [
"geosite:cn"
],
"expectIPs": [
"geoip:cn"
],
"skipFallback": true
},
"https://1.1.1.1/dns-query"
]
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": [
"223.5.5.5/32"
],
"port": "53",
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"1.1.1.1/32"
],
"port": "443",
"outboundTag": "proxy"
},
{
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:private",
"geoip:cn"
],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
前两条规则约束解析器连接的出口:到 223.5.5.5:53 的查询直连,到 1.1.1.1:443 的连接走代理。普通 https:// 形式的 DoH 使用内核路由体系;不要直接替换成带 +local 的形式,后者的连接处理路径不同。这些 IP 与端口规则也会匹配相同目标的其他流量,并非只识别 DNS 内容。
规则顺序不可随意交换。解析器出口规则在前,避免 DoH 地址被后面的 IP 分类规则意外分流;最后一条明确让剩余 TCP、UDP 流量走 proxy,而不是依赖出站数组的默认顺序。若已有局域网、阻断或业务规则,应逐条整合,不能整段覆盖后假定原有行为仍然保留。
判断:先固定解析器出口,再比较应答
先确认 1.1.1.1:443 实际命中 proxy,再观察域名的解析结果。只改 DNS 地址而不检查连接出口,无法验证远端查询是否按预期发送。
直连出站也要核对解析策略
国内域名命中域名规则后,连接会进入 direct。如果该出站使用 Freedom 协议且保留默认解析策略,最终连接可能仍使用系统解析,而不是本文配置的内置 DNS。要让直连出站显式调用内置解析,可核对已有出站并调整其 settings.domainStrategy。
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIPv4"
}
}
这是 outbounds 数组中的单个对象,应修改现有的 direct,而不是再添加一个同名出站。这里的 UseIPv4 和前面的 DNS 查询策略共同构成一个便于定位问题的 IPv4 基线,不代表 IPv6 本身需要禁用。
- 需要双栈时:评估把 DNS 查询策略与 Freedom 解析策略调整为
UseIP,同时检查本地 IPv6 连通性和对应路由。 - 代理出站接收域名时:目标域名可能由远端解析;本地 DNS 结果不一定是远端实际使用的结果。
- 节点地址是域名时:还存在代理服务器自身的解析问题。不要把节点域名唯一的解析路径绑在尚未建立的代理连接上。
在客户端中验证实际配置
v2rayN 是桌面客户端,v2rayNG 使用 Xray 内核,v2flyNG 使用 V2Fly 内核。客户端界面会生成运行配置,因此“编辑框里有字段”不等于“当前内核正在使用该字段”。本文不绑定某个界面版本,验证对象始终是当前节点、运行内核与最终生成的 JSON。
- 保存基线:备份当前可用配置,记录节点、内核版本、系统代理状态以及是否启用虚拟网卡。一次只改变 DNS 和相关路由,避免同时更换节点与传输参数。
- 检查运行文件:确认最终 JSON 包含两项
dns.servers、预期的出站标签和完整规则顺序。配置由界面生成时,应在持久化配置入口修改,不要只编辑会被下次启动覆盖的临时文件。 - 启用诊断日志:短时将
log.loglevel设为debug,重启内核后重新发起请求。日志内容随版本变化,重点查找解析器目标、匹配的出站和错误信息。 - 分开测试:选择一个确认属于
geosite:cn的域名,再选择一个不在该集合中的域名。关闭重复连接,必要时重启应用,避免复用连接掩盖新的 DNS 行为。 - 恢复日常日志:测试完成后把日志级别调回
warning或原值。分享日志前清理节点地址、订阅链接和访问域名等信息。
如果本机具备相应内核命令,可先在配置文件所在目录做语法与加载检查。下面两个命令分别对应 Xray 与 V2Fly 的常见命令行形式,只运行与实际内核对应的一条;配置测试成功不代表上游解析器已经可达。
xray run -test -config config.json
v2ray test -c config.json
不要用 nslookup example.com 223.5.5.5 的结果证明内核 DNS 分流生效。该命令直接查询指定服务器,适合检查这条查询路径是否可用,却没有经过本文的域名分类、回退与代理出口规则。系统 DNS 测试和内核请求测试需要分别记录。
防污染边界与常见故障
这里的“防污染”是通过加密远端查询、固定出口和筛选异常地址来减少错误结果,不是单个字段提供的绝对保证。DoH 保护的是到解析器之间的查询传输;解析器是否可信、应用是否另行查询、系统是否使用缓存,仍然影响最终连接。
国内网站也开始等待很久,先改哪里?
先临时移除国内服务器的 expectIPs,保持其他配置不变后复测。若延迟恢复,检查该域名的实际应答与 geoip:cn 分类是否一致;不要直接增加更多回退服务器掩盖原因。
设置了远端 DNS,为什么还看到本地查询?
先区分查询来自浏览器、系统、节点域名解析还是内核。检查应用的安全 DNS、系统代理范围和 Freedom 的 domainStrategy。内核 DNS 配置不会自动阻止其他进程向外发送查询。
配置一保存就启动失败,怎么定位?
先看第一条错误是否指向 JSON 语法、未知字段或分类数据加载。确认 geosite.dat、geoip.dat 可被内核读取,并核对 direct、proxy 是否真是现有出站标签。
DoH 一直超时,但代理节点能连接?
确认 1.1.1.1:443 的请求命中代理出站,并检查节点到解析器的连通性。核对系统时间与证书错误;不要通过关闭证书验证来绕过失败。必要时单独更换一个可验证的 DoH 端点再比较。
改好以后,为什么网页仍连接旧地址?
退出并重开应用,重启内核,再复测新的连接。浏览器、操作系统、内核和远端解析器都可能有缓存;仅刷新页面可能复用现有连接,不能证明新规则没有生效。
保留一个可解释的最小配置
- 先验证两个解析器与两个出站,再逐步增加自定义域名分类。
- 遇到误分流,先找命中的第一条规则,而不是只看规则列表中是否存在目标规则。
- 需要特定域名始终直连时,同时检查 DNS 匹配、路由优先级和直连出站解析策略。
- 需要限制 DNS 外发时,应另行设计系统层接管与网络策略,不能把本文片段当作完整的流量约束方案。
可维护的 DNS 分流应能回答三个问题:域名为什么选中这个解析器,解析器连接为什么经过这个出站,最终目标为什么直连或代理。先用日志和运行配置回答这三个问题,再增加规则,比堆叠解析器地址更容易定位故障。