之前有寫到一篇介紹 Surge 根據 WiFi 環境變化來自動選擇使用 DNS Server 的文章

每次域名查詢都要去跑一次 Script,先不論有無額外效能損耗,這樣似乎有點不太優雅

前兩天在 Surge 支援論壇裡面,看到某大神寫的一段範例,剛好可以完美解決這個自動切換 DNS 需求

Surge 只有在網路發生變化的時候才會觸發一次,並根據環境自動將 DoH 啟用或者關閉,非常不錯

所以就稍微拿來改一下,用了幾天沒出現什麼問題,就順便在此篇分享並記錄下來

先說一下我自己的需求,我在家中以及常待的辦公室都有自建 AdGuard Home 在 WiFi 局域網內

所以在認識的 WiFi SSID 下的時候,就用 DHCP Server 指定的 AdGuard Home 即可

只有外出使用行動網路或者不認識 WiFi 時候會需要自動切換啟用 NextDNS DoH 服務

清楚明白自己需求後,就可以開始實作了 😚

👆 Surge 的 DNS 設定改成預設,DoH 留空白不填

接著新建一個本機模組,可以啟用 / 關閉 NextDNS DoH 的模組

Surge App -> 模組 -> 建立本機模組,模組內容如下:

1
2
3
4
5
#!name=NextDNS
#!desc=啟用 DoH 加密解析

[General]
doh-server = https://apple.dns.nextdns.io/########

以上第 5 行 ## 部分請自己改成自己的 NextDNS ID,如果你不是用 NextDNS 也可以改成其他 DoH 網址

新加好以後會如下圖

這邊設定好以後,可以先自己手動測試看看模組有沒有正常工作

試著啟用模組跟關閉模組,確認有沒有正確切換到 DoH 與系統預設 DNS,如無問題就可以繼續往下設定

2021/07/28 update

新版 Surge 的 JS 腳本支援直接控制本體,原版大神修改一下可以更精簡了

所以我也把腳本更新一下,目前用以下版本

接下來到 Surge 的腳本編輯器,新建一個 autodns.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
28
29
30
const ssid1 = "SSID1";
const ssid2 = "SSID2";
const name = "NextDNS";
let home = ($network.wifi.ssid === ssid1) || ($network.wifi.ssid === ssid2);

const getModuleStatus = new Promise((resolve) => {
  $httpAPI("GET", "v1/modules", null, (data) =>
	  resolve(data.enabled.includes(name))
  );
});

getModuleStatus.then((enabled) => {
  if (home && enabled) {
    //在家,卻啟用模組 => 關閉
	$notification.post(`關閉 ${name} 模組`, "" ,"");
	enableModule(false);
  } else if (!home && !enabled) {
	//不在家,沒啟用模組 => 啟用
	$notification.post(`啟用 ${name} 模組`, "" ,"");
	enableModule(true);
  } else {
	//其他情況 => 重複觸發 => 結束腳本
	//$notification.post("重複觸發", "", "");
	$done();
  }
});

function enableModule(status) {
  $httpAPI("POST", "v1/modules", { [name]: status }, () => $done());
}

如上第 1、2 行的 SSID1、SSID2 部分請自行新增或者刪減、修改,如有增加或減少請再修改第 4 行的部份即可

第 3 行的 NextDNS 名稱需要跟上面 DoH 模組的第一行名稱對應

最後在 Surge 設定檔裡面 Script 區域加入一行

[Script]
AutoDNS = type=event,event-name=network-changed,script-path=autodns.js

以上設定完畢後,每當 Surge 偵測到有網路變化時候,例如 WiFi 斷線切換到行動網路之類的

就會自動執行一次 autodns.js 的腳本,這個腳本可以根據 SSID 來決定要不要打開或者關閉 DoH 模組

👆 切換 DoH 的時候會有通知提醒

在 Surge 官方推出自動 DNS 切換功能以前,這個方案基本上完美解決我的需求 🖖