DoH部署使用的一些经验分享

DoH的特征

  • 传输加密,DoH规范限制仅在加密链路上使用(https/quic/tls等,策略上不支持裸http)
  • 可以避免On-Path的DNS修改
  • 虽然还没有定论,但是未来的HTTPS-RR相关功能有可能会要求Trust Resolver作为前置依赖

DoH的部署位点

  • Web浏览器
  • 路由器/网关
  • 自己的递归解析服务器

Web浏览器

浏览器端通常会因为信任链的原因而选择直接访问DoH服务器,绕过本地的DNS解析体系。这是合理的,虽然在某些网络环境下会导致DoH完全不可用。

Firefox强制要求HTTPS-RR相关记录只能通过其内置的Trust Resolver获取。Chriomium和Safari虽然支持使用传统DNS获取HTTPS-RR,但是由于运营商的On-Path负优化,导致这类记录无法可靠解析出来,出现随机不能用的情况。因此,为了使自己的浏览器在任何网络环境下都能够使用,有必要对浏览器专门配置DoH。

对于浏览器的DoH配置,Firefox通过一些trick支持为其专门配置代理。但是不推荐对DoH使用代理,此举会完全破坏DoH提供商对用户IP地址的追踪,使得浏览器最终拿到的IP并不是根据用户IP决定的最优地址,而是代理出口的IP地址。此举可能会造成跨大洲的数据流量绕路,对网站运营来说显著提高成本,对用户来说加载变慢带宽变低体验变差。

Firefox默认会启EDNS中对用户IP的隐私化处理(network.trr.disable-ECS),当使用异地的DoH服务器时同样会造成流量绕行,因而推荐将其关闭。EDNS的ECS本身能够对用户IP做掩码处理,因而该隐私选项并不适用于一般上网场景。

注:使用代理服务器代理真实流量时,通常会使用远端DNS解析,此时本地DNS和DoH配置均没有生效

路由器/网关

此部署位置主要优化各类Legacy网络用户的DNS质量。对于支持DoH的应用程序而言通常会选择直接绕过来自本地网络的DNS服务,哪怕它上游也是Trusted Resolver。

通常是部署一个接受UDP53请求,将其封装为DoH再发出的小服务程序(比如https-dns-proxy),搭配网关本身的递归DNS解析器(dnsmasq等)。局域网的DNS服务依旧由dnsmasq等传统工具提供,但是将其上游配置成https-dns-proxy,从而使得整个局域网都吃上可靠DNS。

OpenWRT上的部署方法参考:[OpenWrt Wiki] DoH with Dnsmasq and https-dns-proxy

限于luci功能,自定义的DoH服务器目前只能通过命令行uci进行配置。

自己的递归服务器

并没有多少可供选择的公共DoH服务。国内运营商比如tx和ali提供的服务都需要绑定一个用户ID进行使用,公共接口有请求频率限制。因而搭建自己的DoH服务是有必要的。

目前我使用的方案为dnsproxy,它支持作为forwarder,在接收下游DoH请求并再向上游发出查询,并有可用的EDNS-ECS实现。

由于部署环境下我使用了反代来处理SSL连接,因而需要使用该项目的一个活跃的fork作为部署版本,该版本支持直接处理裸http请求,而无需直接在dnsproxy本身去处理SSL连接。

上游提供商选择

参考:Public recursive name server - Wikipedia

以下结果使用UDP53在hk测试得到,可能依旧受到On-Path影响

  • Google DNS:支持ECS,可以提供本地化的优化结果,但无法使用akamai工具进行验证。自家的工具可以 (refer)
  • Cloudflare:隐私优先,禁用ECS
  • ADGuard:不准确
  • OpenDNS:不可用
  • Yandex:不支持
  • Gcore:不完全可用
  • 阿里:支持,部分可用

EDNS测试工具

  • dig TXT whoami.ds.akahelp.net
  • dig TXT o-o.myaddr.l.google.com

已知问题:

  • api-apps-lb.itunes-apple.com.akadns.net及其相关域名在请求google dns时若ECS具有有效值,会导致DNS REFUSED,使得iPhone无法使用iCloud/Store相关服务
    跟进:akadns.net也是akamai,不知道为啥走google的递归服务器,akamai服务就各种问题
    跟进:https://groups.google.com/g/public-dns-discuss/c/JUc79GnmnQk