Surge 中文白皮书 (草稿第三部分,转发,代理和规则系统)

请求在处理完毕后将被转发。如果 Surge 的出站模式设置为直接连接,那么该请求将被直接发往目标服务器,如果出站模式设置为全局代理,那么将转发给代理服务器。

当出站模式设置被设置为规则判定时,将根据配置的规则决定转发策略。

规则系统

规则系统中有两个基本概念:策略和规则

  1. 策略:描述了 Surge 进行转发的方式,有三种类别:
  • 内置策略:DIRECT、REJECT、REEJCT-TINYGIF、REJECT-DROP
  1. 规则:规则由四个部分组成:类型、条件、策略和参数。当条件满足时,该规则匹配,使用该规则指定的策略。

策略

下面具体说明各种策略的用途

内置策略

内置策略由 Surge 提供,不随配置而变化:

  • DIRECT:将该请求直接发往目标服务器

由于操作系统对用户空间程序(user-space program)的 socket 并没有提供抛弃的操作,Surge 静默抛弃的实现方式是将该 socket 闲置一段时间后再关闭。

同时,如果发往某主机名的请求短时间内大量触发 REJECT/REEJCT-TINYGIF 策略(当前版本的阈值为 30 秒内 10 次),为了避免产生大量资源浪费,Surge 将自动升级策略为 REJECT-DROP 策略。

代理策略

代理策略由用户自己定义,每个策略描述了一个代理服务,当使用该策略时即为通过该代理服务转发请求。

一个简单的代理策略定义行如下:

ProxyA = http, 11.22.33.44, 8080, username=user, password=pass

其中,ProxyA 为策略名,供规则和策略组所使用。第一个参数为代理协议类型,目前 Surge 支持的代理协议类型有:http,https,socks5,socks5-tls,ss,snell,vmess,trojan,以及两个特殊类型 external 和 direct。 第二个参数为代理服务器主机名,第三个参数为代理服务器端口号,后续为 key=value 的参数表,根据协议类型不同需要提供不同的参数。

不同的代理协议类型有其特定的参数,有些参数是所有代理策略通用的,这里单独讲解几个参数,完整参数表请参见手册:

  • tfo:开启 TCP Fast Open,TFO 可以使 TCP 握手时顺带传递第一个数据包,以此降低代理协议握手的时间开销。但是由于这是 2014 年才引入的新特性,如果和目标服务器之前的设备有任何一个不支持该特性,则会导致异常,目前观察到大多数 ISP 的网络都有异常产生的机率,所以除非是内网代理服务器,否则不推荐开启。

direct 类型 (仅限 Surge Mac)

这是一个特别的类型,严格来说并不是一个代理,用于强制使用某一个网卡进行请求。

PolicyName = direct, interface=en2, allow-other-interface=false

请注意,由于 Darwin 内核的限制,使用的网卡必须拥有连接的目标主机的路由表条目,否则无法使用该网卡。

举例说明,比如同时连接了有线网络和无线网路,通过 netstat -rn 命令我们可以看到两个网卡 en0 和 en1 都拥有 default 的全覆盖路由表条目,只是优先级不同。

Internet: Destination Gateway Flags Netif Expire default 192.168.20.1 UGSc en0 default 192.168.20.1 UGScI en1

这种情况下可以使用 direct 策略自由选择 en0 或者 en1 作为出口。

配合 VPN 使用

某些 VPN 连接后,会加入一个很小的内网路由表,由于覆盖小优先级高,可用于访问特定内网资源。在未开启增强模式时,如果出口策略是 DIRECT,Surge 也会按照这个行为进行本地转发。

但如果开启了强模式,由于 Surge 的 VIF 已配置为默认路由,为了能将连接从本地物理网卡发出,出口连接将会强制绑定原先的默认网卡,无视路由表。这会导致 VPN 的内网路由表失效,该情况下可使用 direct 类型策略强制绑定 VPN 的 utun 设备解决。

[Proxy] CorpVPN = direct, interface=utun1, allow-other-interface=true

[Rule] DOMAIN-SUFFIX,internal.corp.com,CorpVPN

external 类型 (仅限 Surge Mac)

external 类型策略可以让 Surge 与其他代理客户端更方便的协同工作。

该功能目前只能通过直接编辑配置实现,策略定义行为: External = external, exec = “/usr/local/bin/local”, args = “-c”, args = “/usr/local/etc/config.json”, local-port = 1080, addresses = 11.22.33.44

其中 args 和 addresses 参数为选填,其他必填。args 和 addresses 字段可以反复使用进行追加。

当使用到该策略时 Surge 会进行以下工作:

  1. 使用 exec 和 args 参数启动该外部程序,之后向 SOCKS5 127.0.0.1:[local-port] 转发请求。

上述 3 和 4 的功能是有重叠的,请尽量使用 addresses 声明使用到的地址以排除 TUN 处理,这样可以减少系统开销,4 的功能是一重额外保护。

策略组

Surge 提供多种不同类型的策略组以满足各种场景的不同需求,在具体讲解各种策略组前,需要先了解连通性测试。

连通性测试

Surge 的多个功能会用到连通性测试,测试方式有 3 种

  1. ICMP Ping 测试:简单的 Ping 测试,用于反映当前物理网络状况。

Mac 版本首页卡片和网络诊断中的路由延迟为该测试结果。

  1. DNS 查询测试:向所有 DNS 服务器并行查询 bing.com 域名的 A 记录,结果为收到响应的最短时间,用于反映当前物理网络状况,同时简单确认具有 Internet 访问。

Mac 版本首页卡片和网络诊断中的 DNS 延迟,Mac 版本主菜单和 iOS 版本通知中心插件的连通性测试延迟为该测试结果。

  1. HTTP 测试:向目标 HTTP 服务器发出 HEAD 请求,计算收到响应头的时间,任意响应数据包均判定为有效。测试地址可自定义,建议选择在全球都有节点的 URL。

Mac 版本首页卡片的 Internet 和代理延迟,策略组的判断基准,网络诊断的代理测试为该测试结果。

策略组使用方法 3 作为判断基准而非方法 1 是因为:

  1. 代理服务器可能有中转,Ping 测试只能表示到达中转服务器的延迟。

url-test 策略组

并发测试所有子策略,选择延迟最低的策略。有以下几个参数

  • url:用于测试的 URL。

fallback 策略组

与 url-test 组基本一致,区别是只关心子策略是否可用而不关心具体延迟,然后从可用策略中选择靠前的策略。可以通过调小 timeout 参数将缓慢线路也标记为不可用。该类型没有 tolerance 参数。

load-balance 策略组

负载均衡组,随机从子策略中选取一个策略使用。

当配置了 url 参数时,会按照 fallback 组的行为进行可用性检查,然后仅从可用的子策略中随机选取。

除 url、timeout、interval外,还有一个参数:

  • persistent:当 persistent=true 时,对于同一目标主机名,将尽量使用同一个策略。避免因出口 IP 不同而触发目标网站的风险控制。但当可用性改变时可能导致策略变化。

ssid 策略组

虽然名字依然是 SSID 策略组,但是功能已经扩展,可根据当前网络的 SSID、BSSID、路由 IP 地址等因素选择子策略。iOS 版本还可以为数据网络指定策略。

规则

Surge 使用规则系统来对选择每个连接的出口策略。规则的匹配方式为自上而下,逐一测试。最末尾规则一定是一个 FINAL 规则,当所有规则都不匹配时使用。

域名规则

当连接的目标主机名符合时,匹配该规则。

  • DOMAIN:严格匹配某域名。

域名和主机名

域名其实是主机名的一种形式,Surge 内部对域名和主机名并没有区分,所有文档所提到的域名和主机名所对应的处理逻辑都是一样的。

比如,DOMAIN,1.2.3.4 规则其实也可以用于匹配目标主机为 IP 地址 1.2.3.4 的连接。DOMAIN,MacBook.local 也可用于匹配 Bonjour 主机名。

IP 地址规则

当连接的目标主机的 IP 地址符合时,匹配该规则。包含 IP-CIDR,IP-CIDR6,GEOIP 三种类型。

当目标主机名是一个域名或主机名时,IP 类型规则会触发本地 DNS 解析。根据解析得到的 IP 地址进行判断。当解析失败是:

  • 如果最终的 FINAL 规则带有 dns-failed 标记,那么将直接匹配 FINAL 规则。

IP 类型规则有一个专有的参数 no-resolve,如果一个 IP 规则带有该参数,那么

  1. 如果目标主机名是一个域名,那么将跳过该规则,不触发 DNS 解析。

由于 DNS 查询有时间开销,所以在配置规则时,最优的方式是尽量先不触发 DNS 解析,将所有会触发 DNS 解析的规则放在底部。这样应使用代理策略的请求就完全避免了在本地进行 DNS 解析。

但是也不用刻意的去完全避免解析,因为一旦决定使用 DIRECT 策略,那么最终还是要进行解析。Surge 有完备的 DNS 缓存系统,不必在意短时间内的重复解析。

不过需要注意,如果某目标主机在本地 DNS 不可被解析,那么一定需要加入对应的规则,在触发 DNS 前就决定策略终止匹配。或者对 FINAL 规则加上 dns-failed 标记并使用代理策略。

HTTP 相关规则

仅对 HTTP 请求有效的规则,包含 URL-REGEX 和 USER-AGENT。

比较特殊的是,只有由于只有进行 MITM 解密后才可获取到 URL,所以 URL-REGEX 对未解密的 HTTPS 连接无效。但是 USER-AGENT 规则却对未解密的 HTTPS 也连接有效,因为程序在使用 HTTP 代理时,会在发送 CONNECT 请求时带上自己 User Agent 的明文。

其他规则

  • PROCESS-NAME:仅对 Mac 版本有效,可以匹配程序名。

规则集

RULE-SET 规则集可以将多个子规则放在一个单独的文件中,便于分享和复用。但是规则集中的规则不可以指定策略,整个规则集指向一个同一个策略。

另外 Surge 自带了 SYSTEM 和 LAN 两个规则集,规则集包含的具体子规则会随 Surge 更新而有所调整。注意 LAN 规则集会触发 DNS 解析。

RULE-SET 和 DOMAIN-SET 的不同

RULE-SET 可包含所有类型的子规则,执行效率和在主配置中的规则没有区别,而 DOMAIN-SET 仅可使用 DOMAIN 和 DOMAIN-SUFFIX 两种形式的内容,使用了特别的逻辑进行优化,在内容非常多时性能有极大的提升。(千条以上,否则两者没有太大的区别)

逻辑规则

可通过 AND,OR,NOT 运算对所有规则类型进行组合使用。如

AND,((PROCESS-NAME,Google Chrome),(PROTOCOL,UDP)),REJECT

可以拦截 Chrome 发出的 UDP 数据包。

iOS Freelance Developer, Technical Advisor

iOS Freelance Developer, Technical Advisor