用 Surge 依网络环境在多个 DoH 服务器间自动切换

TL;DR: 假设你有DoH服务器 D1 和 D2, 你不想在连接 Wi-Fi 热点 X 的时候使用 D1。

  1. 在 DNS - DNS 服务器 - DNS-Over-HTTPS 处填写 D1 和 D2 的地址,用半宽逗号「,」隔开。
  2. 选择脚本 - 新增,填写脚本名称 (如「[email protected]」),选择脚本类型「DNS」,脚本位置选择「本地」。点击「编辑脚本」,贴上以下代码,点击「完成」。
if ($network.wifi.ssid === 'X') {
    $done({ address: '0.0.0.0' })
} else {
    $done({ })
}
  1. 在 DNS - 本地 DNS 映射处点击「新增」,类型选择「脚本」,域名填写 D1,DNS服务器选择脚本「[email protected]」。

之前用 AdGuard Home 自建了 DNS 服务器,一开始通通开放,总有奇怪的 IP 来连接,几乎到了被 DDoS 的程度。即使关闭了 53 端口,依然有 IP 来做做 WHOIS 查询,很讨厌。当然,作为教训,根本就不应该自建开放的 DNS 服务器,AWS 甚至不允许你用 EC2 做这种事。比较安全的做法当然是限制访问 IP,比如仅限 localhost 家庭 IP 地址 (前提是有固定 IP 地址) 访问。但是这样的话手机在外用蜂窝网络访问便成了问题:手机在用蜂窝网络时经常在基站间漫游,IP 也就经常变动。更别提我用双卡,甚至可能会中途切换运营商。

最近发现了 NextDNS, 试用了一段时间,感觉很棒。可惜免费版每月限制 30 万次查询。尝试一周后发现:如果手机的所有请求都用 NextDNS,这个数量对我来说远远不够。

一个很干净的解决方案就出现了:把 AdGuard Home 设置为仅允许家中宽带 IP 访问,全部设备在家用 AdGuard Home 服务器,出门用 NextDNS,把过滤攻击的工作交给 NextDNS 来做。

可是怎么实现呢?我的启发来源于 Stephen 的这篇博客文章 。但是这里的脚本 servers:$network.dns 会回退到路由器/蜂窝网络运营商自己的 DNS 服务器。在途中我还试着安装过 NextDNS 的应用,用 DNS profile,但是依然无法改变回退的结果(不知道是 Surge 的 bug 还是有意为之)。

在折腾了两天(就为了不付每月 2 刀给 NextDNS 🙄 I loathe myself)之后,我终于开窍了:DoH 说到底是 HTTP 请求,第一次访问时也是要做 DNS 解析的啊!只要在不想用某个 DoH 服务器的时候,拒绝解析就行了!就像 AdGuard Home 过滤广告的行为一样,直接返回 "0.0.0.0",或者再加上 "[::]",这个服务器就会被 Surge 忽略。拼图还剩最后一块:Surge 会在网络环境改变时重做 DoH 服务器解析。正合我意。

当然,如果你需要更细粒度的控制,比如不同 SSID 下用不同 DoH 服务器,只需要调整第 2 步的 SSID 和第 3 步的域名即可。

最后由衷跟 NextDNS 说一句对不起🧎‍♀️:这确实是个好服务,如果你懒得维护自己的 DNS 服务器,NextDNS 绝对值得你掏钱。如果你要掏钱的话,何不用用我的推广链接呢!https://nextdns.io/?from=aqpmmuq8

Some rights reserved
Except where otherwise noted, content on this page is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International license