最近的版本中我们暂停了新功能的开发,着重于处理一些遗留的低概率崩溃和内存泄露问题。目前最新的版本中相关问题都已得到了修正,是目前最稳健的一个版本,将于近日发布正式版本。
什么是内存泄露
简单说就是应用因为任何原因,向系统申请了一段内存后未正确释放,导致应用所使用的内存越来越高。
对于 Surge iOS,如果出现持续的泄露,内存占用会不断逼近系统限制,导致被终止重启。对于 Surge Mac,可以观察到内存占用不断提高。
内存泄露问题在计算机科学上一直是一个难题,即使是 iOS/macOS 的系统程序和内置应用,也经常会出现内存泄露的现象。这次修正的数个内存泄露问题也都十分隐蔽,比如当脚本使用 $httpClient 请求数据时,如果 H2 服务端在发送了部分数据后主动中断了该 stream,那可能会导致缓存的部分数据未能被正确释放,这种问题几乎只会在请求特定服务器时才会发生,所以难以被发现。
为此我们重新设计了新的内存泄露检测系统,用于分析这些低概率泄露问题,目前的表现相当良好,崩溃报告系统的数据显示,自 Mac 5.9.2 版本开始已经没有任何用户再遇到过可观测的内存泄露。
什么是内存泄露
简单说就是应用因为任何原因,向系统申请了一段内存后未正确释放,导致应用所使用的内存越来越高。
对于 Surge iOS,如果出现持续的泄露,内存占用会不断逼近系统限制,导致被终止重启。对于 Surge Mac,可以观察到内存占用不断提高。
内存泄露问题在计算机科学上一直是一个难题,即使是 iOS/macOS 的系统程序和内置应用,也经常会出现内存泄露的现象。这次修正的数个内存泄露问题也都十分隐蔽,比如当脚本使用 $httpClient 请求数据时,如果 H2 服务端在发送了部分数据后主动中断了该 stream,那可能会导致缓存的部分数据未能被正确释放,这种问题几乎只会在请求特定服务器时才会发生,所以难以被发现。
为此我们重新设计了新的内存泄露检测系统,用于分析这些低概率泄露问题,目前的表现相当良好,崩溃报告系统的数据显示,自 Mac 5.9.2 版本开始已经没有任何用户再遇到过可观测的内存泄露。
Surge iOS & Mac Beta 更新日志
优化了使用 Smart Group 作为 underlying-proxy (代理链)的表现,在先前的版本中由于架构问题,使用 Smart Group 作为一个代理策略的 underlying-proxy 时,Smart Group 无法发挥全部特性(如动态备用策略切换)。新版本中已经完全解决了这些问题。
注:部分用户询问 Snell 的 reuse 机制在 Smart Group 组中无法使用的问题,请注意这是特意进行的限制,因为 reuse 机制启动的情况下,Smart Group 无法准确评估该代理的表现,同时会导致备用策略切换无法正常运作。
优化了使用 Smart Group 作为 underlying-proxy (代理链)的表现,在先前的版本中由于架构问题,使用 Smart Group 作为一个代理策略的 underlying-proxy 时,Smart Group 无法发挥全部特性(如动态备用策略切换)。新版本中已经完全解决了这些问题。
注:部分用户询问 Snell 的 reuse 机制在 Smart Group 组中无法使用的问题,请注意这是特意进行的限制,因为 reuse 机制启动的情况下,Smart Group 无法准确评估该代理的表现,同时会导致备用策略切换无法正常运作。
Surge Mac Beta 更新日志
新功能:端口转发 Port Forwarding
配置样例
第一个参数为本地监听端口,第二个参数为转发目标,policy 参数选填,如果不填的话将使用标准代理匹配决定策略
该功能常见于使用 SSH 连接服务器 MariaDB 等开发调试场景。
新功能:端口转发 Port Forwarding
配置样例
[Port Forwarding]
0.0.0.0:6841 localhost:3306 policy=SQL-Server-Proxy
第一个参数为本地监听端口,第二个参数为转发目标,policy 参数选填,如果不填的话将使用标准代理匹配决定策略
该功能常见于使用 SSH 连接服务器 MariaDB 等开发调试场景。
我们在 iOS 3415 / macOS 3160 build 中,加入了一项针对 Snell V4 的优化,有望解决 Telegram 偶尔出现卡顿的问题,待观察是否确实有效。
关于 DNS 泄露
我们之前已经科普过 IP 泄露相关知识,近期又收到很多关于 “DNS 泄露” 与 “DNS ECS” 的问题。由于 “DNS 泄露” 在业界并没有一个统一且严格的定义,这里先归纳出两种常见情形,并分别说明其成因和应对措施:
所谓 DNS 泄露可以指:
1. 指的是在使用传统明文 DNS 时,链路中的运营商、防火墙、公共 Wi-Fi 提供者等都可能直接截获或监视你的 DNS 查询数据包,得知你访问的网站域名。
解决方法:
- 使用加密的 DNS 服务器(如 DoH)
- 使用全局代理模式,或者优先匹配的代理规则,使得不在本地进行 DNS 解析即可。
虽然理论上存在风险,然而实践中由于现在 app 存在大量网络请求,同时云服务器交叠复用,除非涉及的网站域名十分小众,否则也很难从 DNS 请求记录中获得有效信息。
2. 指的是访问的目标网站或者使用的 App自身通过技术手段,检测访问者的真实 IP。
具体技术原理是,构造一个随机的二级域名,通过 DNS 查询中的 ECS 机制,获取到查询者的 IP 地址,以此突破访问者的代理保护获得其实际 IP 地址。
但是,这种检测方法存在诸多不确定性,即使成功,也只能获取到用户的区域,而非真实 IP。
解决方法:
- 使用全局代理模式,或者优先匹配的代理规则,使得不在本地进行 DNS 解析即可。
- 使用不支持 ECS 的 DNS 服务器,如 CloudFlare 的 1.1.1.1。
- 自定义 DNS ECS 字段,提供虚假的 IP 地址也可以解决这个问题,但可能导致 CDN 调度混乱,出现解析错误、访问缓慢或完全连不上的情况。
我们之前已经科普过 IP 泄露相关知识,近期又收到很多关于 “DNS 泄露” 与 “DNS ECS” 的问题。由于 “DNS 泄露” 在业界并没有一个统一且严格的定义,这里先归纳出两种常见情形,并分别说明其成因和应对措施:
所谓 DNS 泄露可以指:
1. 指的是在使用传统明文 DNS 时,链路中的运营商、防火墙、公共 Wi-Fi 提供者等都可能直接截获或监视你的 DNS 查询数据包,得知你访问的网站域名。
解决方法:
- 使用加密的 DNS 服务器(如 DoH)
- 使用全局代理模式,或者优先匹配的代理规则,使得不在本地进行 DNS 解析即可。
虽然理论上存在风险,然而实践中由于现在 app 存在大量网络请求,同时云服务器交叠复用,除非涉及的网站域名十分小众,否则也很难从 DNS 请求记录中获得有效信息。
2. 指的是访问的目标网站或者使用的 App自身通过技术手段,检测访问者的真实 IP。
具体技术原理是,构造一个随机的二级域名,通过 DNS 查询中的 ECS 机制,获取到查询者的 IP 地址,以此突破访问者的代理保护获得其实际 IP 地址。
但是,这种检测方法存在诸多不确定性,即使成功,也只能获取到用户的区域,而非真实 IP。
解决方法:
- 使用全局代理模式,或者优先匹配的代理规则,使得不在本地进行 DNS 解析即可。
- 使用不支持 ECS 的 DNS 服务器,如 CloudFlare 的 1.1.1.1。
- 自定义 DNS ECS 字段,提供虚假的 IP 地址也可以解决这个问题,但可能导致 CDN 调度混乱,出现解析错误、访问缓慢或完全连不上的情况。
Surge Mac Beta 更新日志
新增选项 icmp-forwarding,默认开启
在开启增强模式时,为了降低对用户的干扰,Surge 会对所有 ICMP 数据包进行直接转发,这样不影响用户使用 ping 等工具。
但是这可能导致部分极端追求隐私保护的用户产生 IP 泄露,因此新增 icmp-forwarding 选项,可用于关闭该行为。
新增选项 icmp-forwarding,默认开启
在开启增强模式时,为了降低对用户的干扰,Surge 会对所有 ICMP 数据包进行直接转发,这样不影响用户使用 ping 等工具。
但是这可能导致部分极端追求隐私保护的用户产生 IP 泄露,因此新增 icmp-forwarding 选项,可用于关闭该行为。
配置行尾注释 #!REQUIREMENT 升级
- 现在提供
- 被该行尾注释禁用的内容,可以正常在 UI 显示和编辑了,在不满足条件时会显示为禁用状态,若开启将自动移除限制
- 现在提供
#!IOS-ONLY
, #!MACOS-ONLY
, #!TVOS-ONLY
三个简单写法- 被该行尾注释禁用的内容,可以正常在 UI 显示和编辑了,在不满足条件时会显示为禁用状态,若开启将自动移除限制
Surge Mac & iOS Beta 更新日志
[Host] 段支持使用 DOMAIN-SET 和 RULE-SET 进行配置以提高匹配效率。用例:
该功能仅为一些特别的需求所设计,绝大部分用户不需要考虑 DNS 区分解析,详见:https://kb.nssurge.com/surge-knowledge-base/zh/technotes/dns
[Host] 段支持使用 DOMAIN-SET 和 RULE-SET 进行配置以提高匹配效率。用例:
[Host]
DOMAIN-SET:https://example.com/domains.txt = server:https://223.5.5.5/dns-query
RULE-SET:https://example.com/rules.txt = server:https://223.5.5.5/dns-query
该功能仅为一些特别的需求所设计,绝大部分用户不需要考虑 DNS 区分解析,详见:https://kb.nssurge.com/surge-knowledge-base/zh/technotes/dns
Surge Mac Beta 更新日志
我们在先前的版本中将 STUN 服务器更换为了 stun.cloudflare.com,最近的测试中意外发现,该服务器并未完整实现 Surge 检测 NAT 类型所需要的命令,导致 Surge Ponte 配置时,会将所有网络类型报告为 Full Cone NAT (A)。
新版本修正了该问题,如果更新后发现 Ponte 报告 NAT 类型错误无法启动,说明当前网络确实不是 A 类,无法使用直接穿透模式。
我们在先前的版本中将 STUN 服务器更换为了 stun.cloudflare.com,最近的测试中意外发现,该服务器并未完整实现 Surge 检测 NAT 类型所需要的命令,导致 Surge Ponte 配置时,会将所有网络类型报告为 Full Cone NAT (A)。
新版本修正了该问题,如果更新后发现 Ponte 报告 NAT 类型错误无法启动,说明当前网络确实不是 A 类,无法使用直接穿透模式。
Surge iOS & Mac 更新日志
- 现在在开启 HTTP 捕获开关时,将强制打断所有活跃连接,以确保不会因为已存在的长链接导致错过请求。
- 优化与部分 QUIC 客户端的兼容性,如飞书。
- 修正当使用脚本或其他机制修改请求 HTTP 后,统计中的下载数据计量有误的问题。
- 调整了关于 QUIC 转发时处理逻辑的优先级,现在对于一个不支持 UDP 转发的代理策略,将优先考虑 QUIC Block,再考虑回退至 DIRECT 或 REJECT。
- [Mac] 修正绑定出口 interface 时无法使用 utun 设备的问题
- [Mac] 修正 Ponte Server 失败重试时可能不断产生重复的通知的问题
- [Mac] 修复了在特定网络下,Surge Ponte 转发的某一个请求可能被卡住的问题。
- 现在在开启 HTTP 捕获开关时,将强制打断所有活跃连接,以确保不会因为已存在的长链接导致错过请求。
- 优化与部分 QUIC 客户端的兼容性,如飞书。
- 修正当使用脚本或其他机制修改请求 HTTP 后,统计中的下载数据计量有误的问题。
- 调整了关于 QUIC 转发时处理逻辑的优先级,现在对于一个不支持 UDP 转发的代理策略,将优先考虑 QUIC Block,再考虑回退至 DIRECT 或 REJECT。
- [Mac] 修正绑定出口 interface 时无法使用 utun 设备的问题
- [Mac] 修正 Ponte Server 失败重试时可能不断产生重复的通知的问题
- [Mac] 修复了在特定网络下,Surge Ponte 转发的某一个请求可能被卡住的问题。
Surge iOS & Mac 更新日志
- 优化正则匹配的性能表现
- 修正在触发脚本时,HTTP Request Body 有可能未能被正确捕获保存的问题
- 优化正则匹配的性能表现
- 修正在触发脚本时,HTTP Request Body 有可能未能被正确捕获保存的问题
Surge iOS & Mac 更新日志
- DNS over TLS 支持,配置样例 dot://223.5.5.5
- [Mac] 优化通过 Dashboard 新建规则的各种细节
- DNS over TLS 支持,配置样例 dot://223.5.5.5
- [Mac] 优化通过 Dashboard 新建规则的各种细节
关于加密 DNS 的选择
由于部分用户的需求,Surge 最近版本中加入了对 DNS over TLS 的支持,至此 Surge 已完成对所有标准 DNS 协议的支持。
(除了 DNS over TCP,其本质就是 DNS over TLS 的加密前明文,但是测试中发现大多数服务商的 DNS over TCP 都存在严重问题,不具备实用性,故未开放配置)
根据用户反馈和实际测试发现,tls://223.5.5.5 服务端未实现并发查询,使用时可能会出现严重卡顿,不推荐使用。tls://1.12.12.12、tls://8.8.8.8、tls://1.1.1.1 均完整支持并发查询。
具体对比目前支持的所有加密 DNS 协议:
- DNS over HTTP3 和 DNS over QUIC 的表现几乎完全一致,但是由于协议较新,服务端支持经常出现各种问题。且由于基于 UDP 但并非 53 端口,有可能遭遇 QoS 问题。
- DNS over HTTP3/QUIC 在理论上比 DoH 有一点点微弱的优势(丢包时仅影响对应的 stream),但实践中很难体现。
- DNS over TLS 比 DNS over HTTPS 在请求构造和解析上存在微弱优势,但是对于现代计算设备来说完全可以忽略不计。
- DNS over HTTPS 的使用目前最为广泛,服务端兼容性与稳定性高。
综上所述,DNS over HTTPS 是最优选择。不过如果不存在 ISP 污染,依然推荐使用非加密的传统 DNS,以获得最佳性能。
由于部分用户的需求,Surge 最近版本中加入了对 DNS over TLS 的支持,至此 Surge 已完成对所有标准 DNS 协议的支持。
(除了 DNS over TCP,其本质就是 DNS over TLS 的加密前明文,但是测试中发现大多数服务商的 DNS over TCP 都存在严重问题,不具备实用性,故未开放配置)
根据用户反馈和实际测试发现,tls://223.5.5.5 服务端未实现并发查询,使用时可能会出现严重卡顿,不推荐使用。tls://1.12.12.12、tls://8.8.8.8、tls://1.1.1.1 均完整支持并发查询。
具体对比目前支持的所有加密 DNS 协议:
- DNS over HTTP3 和 DNS over QUIC 的表现几乎完全一致,但是由于协议较新,服务端支持经常出现各种问题。且由于基于 UDP 但并非 53 端口,有可能遭遇 QoS 问题。
- DNS over HTTP3/QUIC 在理论上比 DoH 有一点点微弱的优势(丢包时仅影响对应的 stream),但实践中很难体现。
- DNS over TLS 比 DNS over HTTPS 在请求构造和解析上存在微弱优势,但是对于现代计算设备来说完全可以忽略不计。
- DNS over HTTPS 的使用目前最为广泛,服务端兼容性与稳定性高。
综上所述,DNS over HTTPS 是最优选择。不过如果不存在 ISP 污染,依然推荐使用非加密的传统 DNS,以获得最佳性能。
Surge iOS & Mac 更新日志
新增
- per-policy:由策略的 block-quic 参数决定,默认值,即当前版本的行为。
- all-proxy:覆盖代理策略的 block-quic 参数,全部阻止
- all:覆盖所有策略的 block-quic 参数,全部阻止,包括 DIRECT 策略
- always-allow:覆盖代理策略的 block-quic 参数,全部允许
新增
[General]
参数 `block-quic`,该参数用于全局覆盖是否阻止 QUIC 流量的行为,可设置为- per-policy:由策略的 block-quic 参数决定,默认值,即当前版本的行为。
- all-proxy:覆盖代理策略的 block-quic 参数,全部阻止
- all:覆盖所有策略的 block-quic 参数,全部阻止,包括 DIRECT 策略
- always-allow:覆盖代理策略的 block-quic 参数,全部允许
Surge TestFlight Feed
Surge iOS & Mac 更新日志 新增 [General] 参数 `block-quic`,该参数用于全局覆盖是否阻止 QUIC 流量的行为,可设置为 - per-policy:由策略的 block-quic 参数决定,默认值,即当前版本的行为。 - all-proxy:覆盖代理策略的 block-quic 参数,全部阻止 - all:覆盖所有策略的 block-quic 参数,全部阻止,包括 DIRECT 策略 - always-allow:覆盖代理策略的 block-quic 参数,全部允许
Apple TestFlight 系统故障,iOS 版本暂时无法推送更新
在最新的 iOS 版本中,为 Surge 的托管配置、外部资源和模块 HTTP 请求,新增了 X-Surge-Unlocked-Features 字段,用于服务器判定 Surge 已解锁的功能以区分返回结果,如:
X-Surge-Unlocked-Features: proxy-chain, wireguard, ssh, encrypted-dns, body-rewrite, smart-group, load-balance, vmess, trojan, snell-v4, egress-control, response-header-rewrite, doh, shadow-tls-v3, tuic-v5, hysteria, ecn, ss-2022, rule-pre-matching, body-rewrite-jq, port-forwarding, dot