Surge 脚本编写案例
一、本文的目标
网上有各路大神编写的大量优秀 Surge 脚本,能帮大家解决很多问题。这些脚本很强大也比较复杂,当在特定场景下不能满足要求时,自己想改却很难。我一直觉得“授人以🐟不如授人以渔”,熟悉了脚本的编写方法,然后不断熟悉并写出适合自己需求的脚本才是王道。
网络上靠谱儿的 Surge 脚本教程比较少。其实官方文档写得非常清晰了。只不过作者可能是觉得使用 Surge 的同学都是专业技术同学,所以没有做成保姆级教程。本文尝试通过简单的场景和例子,对应文档加以说明,争取使用最简单务实的场景把脚本大体写法说清楚,算是为入门扫清障碍,便于大家阅读文档了解细节的内容。
二、脚本编写规则
Surge 脚本的官方文档在这里:https://manual.nssurge.com/scripting/common.html
使用 Surge 脚本需要两部分工作:
- 第一部分是 Surge 配置文件中的
[Script]
区块中指定脚本规则,每行第一个等号前面的部分是脚本名称
,等号后面是脚本属性(这里只列出最常用的)-
type
:脚本类型http-request
http-response
cron
event
dns
rule
-
script-path
:脚本的路径,可以是配置文件的相对路径、绝对路径或 URL。
-
文档中的举例:
[Script]
script1 = type=http-response,pattern=^http://www.example.com/test script-path=test.js,max-size=16384,debug=true
scropt2 = type=cron,cronexp="* * * * *",script-path=fired.js
scropt3 = type=http-request,pattern=^http://httpbin.org script-path=http-request.js,max-size=16384,debug=true,requires-body=true
scropt4 = type=dns,script-path=dns.js,debug=true
- 第二部分就是编写的脚本,脚本为 JavaScript 文件
就是标准的 JavaScript 语法,脚本中可以使用各种环境变量,需要注意的是必须使用 $done()
来表示执行完成并返回,否则会认为超时。返回的内容以对象形式写在括号中。不需要返回值则括号中内容留空。
三、场景及应用举例
1、根据当前 Wi-Fi 的 SSID 来判断如何解析域名
场景:有一台办公用的服务器,在公司连接公司 Wi-Fi 的时候通过公司内网地址访问,不在公司的时候通过外网地址访问。
- 公司 Wi-Fi 的 SSID:
Compony-Net
- 在公司使用内网地址:
192.168.1.100
- 公司外使用外网地址:
11.22.33.44
思路:为服务器主机指定一个域名(假设为 server.net
),根据当前连接网络的 SSID 来判断是否连接公司 Wi-Fi,再决定如何做域名解析。
(1)Surge 配置文件
中的设置内容
[Script]
server_dns_script = type=dns,script-path=dns.js
[Host]
server.net = script:mocha_tunnel_dns_script
说明:
-
[Script]
区块-
脚本名称:
server_dns_script
-
脚本类型:
dns
-
脚本文件路径:
dns.js
-
-
[Host]
区块- 要解析的域名:
server.net
- 指定解析方式:
script:mocha_tunnel_dns_script
表示以脚本形式解析,使用的脚本为server_dns_script
- 要解析的域名:
(2)JavaScript 脚本
// 连接公司 Wi-Fi
if ($network.wifi.ssid === 'Compony-Net') {
$done({address: '192.168.1.100'})
} else {
$done({address: '11.22.33.44'})
}
$done()
说明:
- 通过
$network.wifi.ssid
判断公司 Wi-Fi - 通过
$done({address: 'xx.xx.xx.xx'})
来返回解析地址
根据文档,该脚本应返回以下内容之一:
-
address<String>
:作为结果使用此 IP 地址。 它必须是字符串中的有效 IPv4/IPv6 地址。 -
address<Array>
:结果使用多个 IP 地址。 -
server<String>
:要求 Surge 通过指定的上游 DNS 服务器查找域。 它必须是字符串中的有效 IPv4/IPv6 地址。 -
server<Array>
:要求 Surge 通过多个指定的上游 DNS 服务器查找域。
2、根据当前 Wi-Fi 的 SSID 来根据规则来选择策略
场景:有一台代理服务器,在公司连接公司 Wi-Fi 的时候通过公司内网地址连接代理服务器,不在公司的时候通过外网地址连接代理服务器。
- 公司 Wi-Fi 的 SSID:
Compony-Net
- 公司内网代理:
192.168.1.100:1234
- 公司外网代理:
11.22.33.44:5678
思路:分别配置内网代理策略和外网代理策略,编写脚本根据 SSID 判断规则,根据规则选择策略。
(1)Surge 配置文件
中的设置内容
[Proxy]
Company = ss, 192.168.1.100, 1234, encrypt-method=aes-256-gcm, password=123
Internet = ss, 11.22.33.44, 5678, encrypt-method=aes-256-gcm, password=456
[Script]
intranet_ssid_rule_script = type=rule,script-path=rule.js
[Rule]
SCRIPT,intranet_ssid_rule_script,Company
NOT,((SCRIPT,intranet_ssid_rule_script)),Internet
说明:
-
[Proxy]
区块:代理策略 -
[Script]
区块-
脚本名称:
intranet_ssid_rule_script
-
脚本类型:
rule
-
脚本文件路径:
rule.js
-
-
[Rule]
区块- 符合内网匹配规则:使用
Company
策略 - 符合外网匹配规则:使用
Internet
策略 - 每条规则组成:
-
NOT
:取反规则,根据情况选用 -
SCRIPT
:表示脚本类型的规则 -
intranet_ssid_rule_script
:脚本名称,在[Script]
中指定 - 最后一段是
策略名
-
- 符合内网匹配规则:使用
(2)JavaScript 脚本
// 连接公司 Wi-Fi
let is_intranet = $network.wifi.ssid === 'Compony-Net'
$done({matched: is_intranet})
说明:
- 通过
$network.wifi.ssid
判断公司 Wi-Fi - 通过
$done({matched: is_intranet})
来返回解析地址
根据文档,该脚本应返回如下内容:
{matched: is_intranet}
-
matched<Bool>
:返回是否匹配。
四、参考资料
-
Surge 脚本的官方文档:https://manual.nssurge.com/scripting/common.html
-
一些脚本样例:
(完)