
背景:路由没错,解析错了也一样打不开
sing-box 是一个开源的通用代理平台:既可以跑在服务器上,也可以跑在电脑、手机上当客户端,决定每条流量走哪个出站(走哪个节点、直连还是拦截)。昨天那篇讲的是出站分组:节点挂了不断线的做法。今天讲它经常被忽略的另一半:DNS。
DNS 就是把域名翻译成 IP 地址的服务。你在浏览器输入一个域名,设备要先问 DNS 服务器拿到 IP,才能去连接。关键顺序是:解析发生在连接之前。路由规则是按域名或 IP 决定流量走哪条路,但如果解析这一步就拿到了错误的 IP,后面的路由规则再正确也没用——要么连到错误的机房,要么直接被挡住。
前置知识:一份能跑起来的 sing-box 客户端配置,知道出站(outbound)是配置里的一组条目、每条有一个名字(tag)。路由规则写法见本站的路由规则指南。
先建立正确模型:两路 DNS,各问各的
分流场景下,DNS 通常要分成两路:国内域名问本地 DNS,直接走本地网络解析,拿到国内机房的 IP;海外域名问代理侧 DNS,解析请求本身也要走代理出站,否则本地网络返回的可能是被干扰的结果。
sing-box 的 dns 配置就是干这件事的。按官方 DNS 配置文档,它由三部分组成:servers(有哪些 DNS 服务器)、rules(哪个域名问哪台)、final(没匹配上的默认问哪台)。下面是一个最小可用的两路模板,只演示结构,域名匹配部分按你自己的规则集调整:
"dns": {
"servers": [
{
"tag": "dns-remote",
"address": "tls://1.1.1.1",
"detour": "proxy"
},
{
"tag": "dns-direct",
"address": "223.5.5.5",
"detour": "direct"
}
],
"rules": [
{
"rule_set": "geosite-cn",
"server": "dns-direct"
}
],
"final": "dns-remote",
"strategy": "prefer_ipv4"
}
这里有三个容易写错的点:
detour才是「解析走哪条路」。dns-remote的detour必须填你的代理出站 tag(上面用proxy代指你自己的分组名)。只写了海外 DNS 的地址、没写detour,解析请求就还是走本地网络,等于没分流。final是兜底,不是摆设。没被任何规则命中的域名都会问final。分流场景下final一般设成代理侧那台;如果设成直连那台,所有海外域名都会先走本地解析,分流就漏了。- 规则集要另外定义。上面
geosite-cn这类规则集需要在route.rule_set里另外声明来源和下载方式,不是只在dns.rules里写个名字就生效。
strategy 是解析时 IPv4/IPv6 的偏好,官方文档给出的可选值是 prefer_ipv4、prefer_ipv6、ipv4_only、ipv6_only。如果你本地 IPv6 并不通,prefer_ipv4 是稳妥的起点。
症状对照:三种打不开,对应三种错法
| 症状 | 大概率原因 | 先改哪里 |
|---|---|---|
| 海外站打不开,或解析到的 IP 明显是国内机房 | 代理侧 DNS 没走代理出站,detour 缺失或填错 | 检查 dns-remote 的 detour 是否指向你的代理出站 |
| 国内站变慢、绕远路 | final 设成了代理侧,所有域名都先走代理解析 | 把国内规则指向直连 DNS,final 只兜底海外域名 |
| 改了配置,故障原样不动 | DNS 缓存没过期,或请求根本没经过 sing-box | 重启 sing-box、清系统缓存、确认 DNS 接管生效(见下文) |
还有一类容易误判的「假故障」:如果你用了 FakeIP,系统里看到 198.18.x.x 这类地址是正常的——FakeIP 是先给域名发一个保留段的假 IP、等真正建立连接时再换成真实 IP,不要把它当成真实 IP 加进白名单。只有某个应用明确不支持 FakeIP 时,才需要把该域名排除出去。
排错三步:从外到内,别一上来就重装
第 1 步:对比解析结果,确认错在哪一层
先别动配置。分别在代理开启和关闭的状态下,对同一个打不开的域名做解析,对比两次返回的 IP:
nslookup example.com
dig example.com
两次 IP 归属地完全一样,说明解析根本没走你预期的那路 DNS——问题在分流,不在节点。example.com 只是演示写法,实测时换成真正打不开的域名。
第 2 步:按顺序核对三个字段
打开你的 dns 配置,按这个顺序看,不要跳着看:
servers里代理侧那台有没有detour,detour的值是不是你真实的出站 tag(不是照抄模板的proxy)。rules里国内域名是不是指向了直连 DNS,规则的匹配方式(规则集或域名后缀)有没有写错、拼错。final是不是代理侧那台。final为空时默认用第一台服务器,顺序一换兜底就跟着变,最好显式写清楚。
第 3 步:确认请求真的经过了 sing-box
这是最容易漏的一步。即使 dns 配置全对,如果 DNS 请求根本没进 sing-box,配置等于没生效。常见 bypass 有三种:
- 没开 TUN、也没做 DNS 劫持:系统 DNS 还是运营商那台。按客户端说明开启 TUN 模式,或在路由里配好 DNS 劫持规则。
- 浏览器 Secure DNS:浏览器自己去问了另一台 DNS,排错时先关掉再测。
- 手机「私人 DNS」:会绕过系统下发的 DNS,排错时先关掉再测。
做完上面三步,再跑一次配置校验和重启:
sing-box check -c config.json
校验通过再重启 sing-box,然后清空系统 DNS 缓存重新测试。如果这时恢复了,说明之前是缓存或接管问题,不是配置写错。
收尾清单:写 DNS 配置时顺手核对
- 代理侧 DNS 写了
detour,且指向真实的出站 tag。 - 国内规则指向直连 DNS,
final显式指向代理侧。 - 规则集在
route.rule_set里有定义,不是只在dns.rules里写了个名字。 - 改配置后先
sing-box check,再重启、清缓存,最后才怀疑是节点问题。 - 浏览器 Secure DNS、手机私人 DNS 这类 bypass,排错时先关掉再测。
DNS 分流没有一劳永逸的模板:规则集会更新、网络环境会变,出问题时按「对比解析结果 → 核对三个字段 → 确认接管生效」走一遍,就能定位是解析的问题还是节点的问题,而不是两边一起乱改。
