没有 VPN,加密 DNS 只隐藏查询,不隐藏你的地址
加密 DNS 只保护与单个解析器之间的一次交换。它既不隐藏你的地址,也不让解析器失明,所以先确定目标,再去看泄漏测试。
一个显示你家网络的 DNS 泄漏测试,既不能证明加密 DNS 失败,也不能证明它成功。这个测试只回答一个问题:这次查询从这个网络发往了哪个解析器。它是不是问题,取决于你在防谁、防什么。
先写下目标,再运行任何测试。
第 1 步:说清你真正想要的保护
三个目标常被混在一起。你可能想让路径上的观察者不再读取查询。你可能想让某个解析器不再收到这些查询。你可能想让访问的网站看不到你家的地址。加密 DNS 服务第一个目标,改变谁来满足第二个目标,对第三个目标毫无作用。
VPN 服务第三个目标,并视服务商而定服务第一个目标。两者不是彼此的包含关系。
第 2 步:选择解析器并验证其身份
DNS over TLS 把查询包进与解析器之间的 TLS 会话,DNS over HTTPS 则把它包进 HTTP 请求;RFC 7858 与 RFC 8484 分别描述两者,都不需要隧道。运维上真正重要的是证书要针对你配置的名字做校验,因为与错误一方建立加密会话,比与正确一方使用明文更糟。这意味着在平台提供时选择严格模式,而不是校验失败就回退的机会模式。信任该设置之前,直接检查会话:openssl s_client -connect 9.9.9.9:853 -servername dns.quad9.net -brief。
握手应当报出你配置的解析器,并返回一条可校验的证书链。
第 3 步:决定失败时的行为
每种实现都对不可达的加密解析器有策略,而这个策略就是隐私决定。严格模式让查询失败,这很显眼也很烦人。机会模式改用明文重试,这不可见,而且恰好在最要紧的那天让目标落空。有意识地做出选择,然后把选择记在需求旁边。
在 systemd-resolved 上,应选择DNSOverTLS=yes而不是opportunistic;在 Android 上,应选择 Private DNS 主机名模式而不是自动。
用下面的命令检查实际生效的是什么:resolvectl status | grep -i -A1 "dns over tls",因为从未重新加载的 drop-in 文件不会改变任何东西。
第 4 步:检查应用是否遵循系统解析器
自带安全 DNS 设置的浏览器会完全绕过系统配置,内嵌解析器的容器运行时、读取硬编码列表的语言运行时也一样。要么让它们跟随系统,要么显式配置并记录下来。然后逐个查看它们的回退行为,因为它们并不都以失败关闭。实际清单很短:浏览器、容器运行时,以及你同时运行的任何 VPN 客户端。
组织的内部域名留在获批的内部解析器上。为了让测试看起来整齐而把它们发往公共服务,是在故意制造另一个问题。
第 5 步:对照需求去读泄漏测试
报告意外解析器的测试只是线索,不是结论。它观测到的可能是你预期的加密解析器、某个应用专有设置,或你不知道的明文回退。把报告的解析器与第 2 步的配置对比,再把结果与第 1 步的目标对比。
如果目标是让查询远离本地网络,那么显示你常用解析器的测试就是真实发现。如果目标是浏览时的匿名性,任何 DNS 设置都不可能提供它。
用目标的语言写下验收线:这些查询在这些条件下使用这个已验证的解析器。任何更宽的说法都是你无法检验的主张。