Surge for Mac 设置部分域名使用系统 DNS

需求

在局域网中架设了一些服务,需要实现同一个域名,在局域网中的设备的访问时解析到局域网的服务器地址,外网则解析到经过内网穿透的公网服务器地址。

因此在局域网中架设了一个 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 服务器。

1
2
3
[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,使用以下脚本进行了处理:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var hostname = $domain;
// 这些网络下使用路由器下发的 DNS
var ssids = [
    'SSID1',
    'SSID2'
];
// 如果路由器提供的 DNS 包括这些 DNS, 就使用路由器下发的 DNS
var dnss = [
    '192.168.1.11',
];

ssids = '^(' + ssids.join('|') + ')$';
ssids = new RegExp(ssids);
dnss = '"(' + dnss.join('|') + ')"';
dnss = new RegExp(dnss);

var ssid = $network.wifi.ssid ? $network.wifi.ssid : '';  //有线网络

var ssidMatched = ssid.match(ssids);
var dnsMatched = JSON.stringify($network.dns).match(dnss);

// 如果在指定的 SSID 下 或者 路由器下发的 DNS 是 AdGuard
if (ssidMatched || dnsMatched) {
    $done({ servers: $network.dns })
} else {
    $done({})
}

将文件保存到配置目录中,例如文件名为system-dns.js,配置文件对应修改:

1
2
3
4
5
6
[Host]
example.com = script:system-dns
*.example.com = script:system-dns

[Script]
system-dns = type=dns,script-path=system-dns.js

即可实现 在指定网络下 或者 存在指定的 DNS 服务器 时,对 指定域名 使用路由器下发的 DNS。

简单版

如果没有网络环境的要求,还可以直接将脚本写为:

1
$done({ servers: $network.dns })

在配置文件中设置 script:system-dns 为指定域名使用代理,这样指定的域名就会永远使用上游网络下发的 DNS 了。

所参考的 原脚本 实现了更复杂的功能,逻辑是 在指定网络下 或者 存在指定 DNS 服务器时,或者域名匹配到规则时,均使用上游 DNS,有需求可以参考。

0%