使用 DNS over HTTPS (DoH) 解决 DNS 不可靠的问题

为了防止运营商以及其他妖魔鬼怪伪造修改 DNS 响应,之前采用的方案是使用多个不同地区的 DNS 和非常规端口,再加上常见虚假 IP 的黑名单。这样一直使用了很久,虽然说,DNS 响应是正确了,但难免也有些弊端:

  • 由于使用了其他地区的 DNS,访问国内服务的时候,往往不会得到最优的 CDN 节点。这一点也可以通过手动指定 EDSN 解决,但在国内复杂的网络环境下,如果经常在不同运营商之间切换,则略显麻烦。
  • 其他地区的 DNS 服务经常连接不稳定,平日里还好,但总有那么一段时间,会异常不稳定。

最近,了解到了 DNS over HTTPS (DoH),然后初步尝试了下,发现能很好的解决上面提出的两个痛点,不过在刚使用的时候,还是遇到了一些问题。我首先想到的是在 OpenWrt 上部署,搜索一番后,我安装了 Unbound,然后配置中添加

forward-zone:
    name: "."
    forward-tls-upstream: yes
    forward-addr: 2001:4860:4860::8888@853#dns.google
    forward-addr: 2001:4860:4860::8844@853#dns.google
    forward-addr: 8.8.8.8@853#dns.google
    forward-addr: 8.8.4.4@853#dns.google

不过效果和我想的似乎不太对,要么响应是伪造的,要么超时,似乎和普通的 DNS 没什么区别,我猜因该是配置写错地方了吧?纠结搜索一番后,发现我一开始就弄错了方向,Unbound 提供的是 DNS over TLS (DoT)而我想要的是 DNS over HTTPS (DoH) ,无语。

正确的操作因该如下:

  • OpenWrt 安装 https_dns_proxy

  • 我选择使用红鱼 DNS,所以修改 /etc/config/https_dns_proxy

    option url_prefix 'https://rubyfish.cn/dns-query?'
    
  • 修改 OpenWrt 里的 Dnsmasq,将 DNS 请求转发到 127.0.0.1#5053 (端口取决于 /etc/config/https_dns_proxyoption listen_port 选项)

  • 重启 https_dns_proxy

    /etc/init.d/https_dns_proxy restart
    

至此,OpenWrt 安装完成,接下来要给 MIUI 进行设置,这个有点特殊,不像原生 Android 能直接设置,MIUI 把这个设置界面隐藏了,所以有点繁琐。

  • 安装打开 QuickShortcutMaker

  • 切换到 活动 标签

  • 搜索 设置,点击左侧箭头展开,找到 更多连接方式 (带有 NetworkDashboardActivity)关键词,点击启动

  • 点击 私人 DNS ,填入 rubyfish.cn

至此,MIUI 设置完成