记一次DNS配置错误事件
为方便日常使用,并能够在 Linux 下畅玩 Dead or Alive: Xtreme Venus Vacation,本人在之前进行了 *** (以下简称米哈游代理,请注意,本文使用的是 Meta 内核) TUN 模式的相关配置。然而,25 年 3 月 5 日晚,当我高兴的打开 CF 准备进行一场激情四射的 Div 3 VP 时——Chrome 显示找不到 IP 地址。经过几个小时的排查,最终把问题定位到了米哈游内核的 dns 配置文件部分,并写下本文,介绍问题的具体原因和解决方案。
DNS 配置简介
Linux 内核提供了一种名为 TUN 的虚拟网卡设备,使得用户能够处理三层数据包,进行流量代理。米哈游内核提供了基于 TUN 的虚拟网卡模式,可以在 config.yaml 中进行设置。
一般来说,在配置 TUN mode 时,需要进行 DNS 配置,以应对不同的域名解析需求 (如使用国内的 DNS 解析国内网站,使用国外的服务器解析国外网站以获得更准确的结果)。在米哈游代理的 dns 模块中有这样一些配置选项:
enhanced-mode: DNS 处理模式,本文默认采用redir-host而非fake-ipprefer-h3: 倾向使用 HTTP3respect-rules: 在向 DNS 发送请求报文时是否使用rules中的规则进行分流,仅在proxy-server-nameserver非空时可开启,且不建议与prefer-h3一起使用default-nameserver: 用于解析其他 DNS 服务器域名的 DNS 服务器,必须是 IP,可以使用加密proxy-server-nameserver: 用于解析proxies配置项中代理服务器域名的 DNS 服务器,可选项nameserver: 默认的解析域名服务器fallback: 后备域名解析服务器fallback-filter: 过滤条件,满足条件的使用fallback进行解析geoip: 是否使用 GeoIP 进行判断geoip-code: 国家代码缩写,默认值为CN,不匹配该国家代码的 IP 均视为被污染 (即使用fallbackDNS)geosite: 匹配到该部分的域名被视为被污染,使用fallback进行解析ipcidr: 匹配到这一部分网段的 IP 被视为被污染,使用fallback进行解析;240.0.0.0/4是一个常用的屏蔽网段,被 DNS 屏蔽的网站将会返回到这个网段上
以下是米哈游代理处理域名解析的流程图 (图源官方文档)
根据流程图,我们可以规定一种常见的使用方法 (大部分包含分流的 DNS 配置均采用下面范式),以实现域名解析的分流:
- 填写一个一定可用的
default-nameserver进行 DNS 服务器域名的解析,一般采用国内 DNS - 对于国内域名,使用默认
nameserver项进行解析,一般采用国内 DNS - 填写对应的
fallback-filter项,使得国外域名均被视为污染项,并重新使用fallback中定义的 DNS 服务器进行解析,一般采用国外 DNS
米哈游内核在确定了向 nameserver 或 fallback 组发送解析请求后,向同组内的各个 DNS 服务器同时发起请求,并选择相应最快的有效请求作为结果。
实际上,DNS 服务器也是一种“服务器”,所以在访问 DNS 服务器的时候,我们也可以选择使用代理服务器来访问 DNS 服务器,注意,在使用代理服务器访问 DNS 服务器时,必须要先设置 proxy-server-nameserver,或者确保选择的代理服务器本身是不需要解析的 IP 地址,否则会出现鸡生蛋、蛋生鸡的问题。
根据米哈游内核官方手册和 Github 上的示例配置可知,在访问某一 DNS 服务器时,若未进行特殊配置,默认使用出口网卡发起请求,这意味着如果无法在国内访问设定的所有 DNS 服务器,则域名解析将会失败,并在浏览器中返回未找到 IP 的错误提示。
若要开启对特定的 DNS 服务器的代理访问,可以使用附加参数进行指定,指定的对象是网卡 (接口)/代理组/RULES,其中 RULES 代表按照路由规则进行代理连接,等同于对单个 DNS 服务器配置开启 respect-rules,参数使用 # 与原地址进行连接,如 '8.8.8.8#RULES';当指定的附加参数无效时,将会回退到出口网卡发送解析请求。
DNS 加密查询
DoT (DNS over TLS) 和 DoH (DNS over HTTPS) 是两种常见的 DNS 加密查询技术,其端口号分别为 853 和 443。通过 DoT 和 DoH 加密的 DNS 查询服务能够避免被中间用户监听,防止隐私泄漏。
然而,出于一些特殊的原因,国内用户可以“安全”地使用国内 DNS 的 DoT 和 DoH 功能,而无法使用国外 DNS 的相关功能,这也是本次事件的直接原因。
在上面的 DNS 配置中,每一项服务器配置均可以使用 udp、tcp、DoT、DoH 四种类型,其 URL 协议前缀分别为 udp:// (默认,可省略)、tcp://、tls://、https://。
事件经过
5 日晚,在访问 codeforces.com 时,浏览器显示“找不到对应的 IP 地址”,对于所有的境外网站均无法找到对应 IP,国内网站均可以正常使用:

原始的配置文件如下:
dns:
enable: true
use-hosts: true
use-system-hosts: true
respect-rules: false
listen: 0.0.0.0:1053
ipv6: false
default-nameserver:
- 223.5.5.5
- 223.6.6.6
- 119.29.29.29
- tcp://223.5.5.5
- tcp://223.6.6.6
- tcp://119.29.29.29
enhanced-mode: redir-host
nameserver:
- 114.114.114.114
- tcp://223.5.5.5
- tcp://223.6.6.6
- tls://dns.google:853
- tls://8.8.8.8:853
- tls://8.8.4.4:853
- tls://dns.alidns.com
- tls://223.5.5.5
- tls://223.6.6.6
- tls://1.12.12.12
- https://dns.google/dns-query
- https://8.8.8.8/dns-query
- https://8.8.4.4/dns-query
- https://dns.alidns.com/dns-query
- https://223.5.5.5/dns-query
- https://223.6.6.6/dns-query
- https://1.12.12.12/dns-query
fallback:
- tls://8.8.4.4
- tls://1.1.1.1
- https://8888.google/dns-query
- https://1.0.0.1/dns-query
- https://doh.opendns.com/dns-query
proxy-server-nameserver:
- https://doh.pub/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
tun:
enable: true
stack: system
auto-route: true
auto-redirect: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
device: utun0
strict-route: true
本人使用的系统使用 systemd-resolved (/etc/systemd/resolved.conf) 进行域名解析,其配置如下:
[Resolve]
DNS=127.0.0.1
FallbackDNS=114.114.114.114
DNSStubListener=no
显然,向 53 号端口请求的所有域名解析被米哈游内核提供的 dns-hijack 劫持,并交给正在 1053 号端口的服务处理。这是一个典型的分流解析配置,国内网站使用 nameserver 中的 DNS 服务器进行解析,而国外网站使用 fallback 进行解析,同时,default-nameserver 均为国内 DNS,以确保能够正确分流。
使用 ip route show 查看默认路由表,虚拟网卡 utun0 有相应的路由规则,正常:

使用 dig 命令发送 DNS 解析请求,返回 SERVFAIL,该返回码表明 DNS 服务器不可用或者不存在

以上测试均在 TUN mode 打开,米哈游内核 DNS 解析器打开,systemd-resolve 使用米哈游内核 DNS 解析器情况下完成。调回正常设置后,浏览器报错变为“响应时间过长”,不再出现“无法找到 IP 地址”。
为何出现找不到 IP 地址?
如果细看 fallback 中的 DNS 配置项会发现,里面只使用了谷歌公共 DNS 和 CF 公共 DNS,并未使用其他小众 DNS,且这两者在国内是可以正常使用的。对 fallback 配置项进行调整:
- 添加
8.8.8.8或udp://8.8.8.8: 解析正常 - 添加阿里云 DNS 服务器 (四种类型中任意一种): 解析正常
- 添加其他国外 DNS 服务器的 DoT 和 DoH 服务: 无论添加多少,都无法正常解析
- 关闭米哈游内核 DNS 功能,使用 systemd-resolved 默认配置进行解析: 解析正常
于是答案呼之欲出——无法在没有代理的情况下访问 DoT 或 DoH 国外 DNS,具体原因尚未明确,可能是由于笔者当地正册更改引起的。
为了验证猜想,我们需要使用代理节点进行 DNS 查询。故使用官方文档中提到的附加参数 #RULES 或 #策略组,并将策略组选择为可以正常使用的代理节点。经测试,经过代理后可以正常使用国外的 DoT 和 DoH 服务。
解决方案
附加参数 (不推荐)
可以使用附加参数 #RULES 或 #策略组,但有以下缺点:
- 对每个 DNS 服务器都要写入附加参数,较为繁琐
- 节点供应商给出的配置文件中配置组常带有 Unicode 表情字符,yaml 可以正常解析,但打字较为不便
- 选择的策略组必须时刻保持可用状态,否则会使得无法进行域名解析,在没有安装本地 Dashboard 的机器上尤为不便
使用 respect-rules 选项
开启 respect-rules 选项后,DNS 服务器也会通过配置中的 rules 来进行分流,无需对每个 DNS 都写一个附加参数,缺点如下:
- 不建议和
prefer-h3一起使用 - 与附加参数相同,
rules分配到的策略组需要时刻保持可用状态,否则无法进行域名解析,对无本地 Dashboard 的用户不友好
在 fallback 配置项中写入国内可用的 DNS 服务器
选择国内的 DNS 服务器如阿里云等 (非加密、DoT、DoH 均可用),对于大部分国外网站都能够进行正常解析,缺点如下:
- 国内 DNS 服务器可能屏蔽部分国外网站
使用非加密的国外 DNS 服务器
放弃使用 DoT 和 DoH 服务,直接使用 udp 协议的国外 DNS 服务器,缺点如下:
- DNS 请求明文传输,失去安全性
对于国内外的 DNS 服务器汇总可以参考网友整理,个人修改后的配置如下 (国内 DNS 均使用加密,国外不使用加密),可供参考
ipv6: false
external-ui: ui
external-ui-url: "https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip"
hosts:
time.facebook.com: ntp.sjtu.edu.cn
time.android.com: ntp.sjtu.edu.cn
dns:
enable: true
prefer-h3: true # 优先使用 HTTP3
use-hosts: true
use-system-hosts: true
respect-rules: false # 是否对 DNS 请求使用 Rules 进行分流
listen: 0.0.0.0:1053
ipv6: false
default-nameserver: # 用于解析 DNS 服务器的 DNS 服务器, 可以使用加密
- 114.114.114.114 # 114 DNS
- 223.5.5.5 # AliDNS
- 223.6.6.6 # AliDNS
- 119.29.29.29 # DNSPod
- tcp://223.5.5.5
- tcp://223.6.6.6
- tcp://119.29.29.29
enhanced-mode: redir-host
nameserver: # 默认的 DNS 服务器, 用于解析国内域名
- 114.114.114.114 # 114 DNS
- tls://dns.alidns.com # AliDNS
- tls://223.5.5.5 # AliDNS
- tls://223.6.6.6 # AliDNS
- tls://dot.pub # DNSPod
- https://dns.alidns.com/dns-query
- https://223.5.5.5/dns-query
- https://223.6.6.6/dns-query
- https://doh.pub/dns-query
fallback: # 回滚 DNS 服务器, 用于解析国外域名
- 8.8.8.8 # Google
- 8.8.4.4 # Google
- 1.1.1.1 # Cloudflare
- 1.0.0.1 # Cloudflare
- 208.67.222.222 # OpenDNS
- 208.67.220.220 # OpenDNS
- 9.9.9.9 # Quad9
- 149.112.112.112 # Quad9
- 77.88.8.8 # Yandex
- 77.88.8.1 # Yandex
- 84.200.69.80 # DNS.Watch
- 84.200.70.40 # DNS.Watch
- 216.146.35.35 # Oracle
- 216.146.36.36 # Oracle
- tls://8.8.8.8
- tls://8.8.4.4
- tls://1.1.1.1
- tls://1.0.0.1
- tls://208.67.222.222
- tls://208.67.220.220
- tls://dns.quad9.net
- tls://common.dot.dns.yandex.net
- tls://77.88.8.8
- https://dns.google/dns-query
- https://cloudflare-dns.com/dns-query
- https://1.1.1.1/dns-query
- https://doh.opendns.com/dns-query
- https://dns.quad9.net/dns-query
- https://common.dot.dns.yandex.net/dns-query
- https://77.88.8.8/dns-query
# direct-nameserver:
# - system
# direct-nameserver-follow-policy: false
fallback-filter:
geoip: true
geoip-code: CN
# geosite: # 开启此项可能无法使用本地 Dashboard
# - gfw
ipcidr:
- 240.0.0.0/4
tun:
enable: true
stack: system
auto-route: true
auto-redirect: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
device: utun0
strict-route: true
笔者非网络相关专业人士,如文中有错误,欢迎在评论区指正,感谢!

浙公网安备 33010602011771号