在局域网中架设了一些服务,需要实现同一个域名,在局域网中的设备的访问时解析到局域网的服务器地址,外网则解析到经过内网穿透的公网服务器地址。
因此在局域网中架设了一个 adguard Home 服务器,在实现广告隐私过滤的基础上设置了对应的重写规则,并将路由器 DHCP 下发的 DNS 地址改为 AdGuard Home 的地址。
由于其他局域网设备都是使用的 Openwrt 的透明代理,因此之前一切都十分正常,直到一台 MacBook 的加入。
MacBook 使用的是 surge,并且进入了增强模式,因此 Surge 会使用 Fake-IP 模式,并接管系统的所有 DNS 解析,导致 AdGuard Home DNS 无法生效。
关于代理环境下 DNS 解析的详情,可以阅读 浅谈在代理环境中的 DNS 解析行为 | Sukka's Blog。
尝试解决
翻阅 Surge 的文文件,发现它提供了一个 Assigning DNS Server 的功能,通过 hostname = server:dns-server
来指定指定域名的 DNS 服务器。
[Host]
exaple.com = server:8.8.8.8
*.exaple.com = server:system
参照上例,为需要的域名指定 server:system
,但是发现进入增强模式后,依然交给了 Surge 配置中的 DoH 服务器来解析,并没有回落到系统解析。
通过 cat /etc/resolv.conf
查看系统的 DNS 服务器,发现系统的 DNS 服务器在进入增强模式后被设置为了 198.18.0.2
,因此代理请求依然被 Surge 接管。
在社区中搜索到 mac 进入 doh 后,在增强模式下:host 模块 指定 syslib 的域名还是走的 doh – Surge Tech Community,开发组回复 「设计如此,增强模式下 syslib 无效,会导致回环查询」。既然是特性,那就只能寻找新的解决方案了。
使用 Script
Surge 提供了很强的脚本功能,可以处理 DNS 请求,因此就可以用脚本来对 DNS 做处理。参考 dns.js,使用以下脚本进行了处理:
var hostname = $domain;
// 这些网络下使用路由器下发的 DNS
var ssids = [
'SSID1',
'SSID2'
];
// 如果路由器提供的 DNS 包括这些 DNS, 就使用路由器下发的 DNS
var dnss = [
'192.168.1.11',
];
ssids = '^(' + ssids.join('|') + ')
将文件保存到配置目录中,例如文件名为 system-dns.js
,配置文件对应修改:
[Host]
example.com = script:system-dns
*.example.com = script:system-dns
[Script]
system-dns = type=dns,script-path=system-dns.js
即可实现 在指定网络下 或者 存在指定的 DNS 服务器 时,对 指定域名 使用路由器下发的 DNS。
简单版
如果没有网络环境的要求,还可以直接将脚本写为:
$done({ servers: $network.dns })
在配置文件中设置 script:system-dns
为指定域名使用代理,这样指定的域名就会永远使用上游网络下发的 DNS 了。
所参考的 原脚本 实现了更复杂的功能,逻辑是 在指定网络下 或者 存在指定 DNS 服务器时,或者域名匹配到规则时,均使用上游 DNS,有需求可以参考。