一直以来 Surge iOS/macOS 都是使用的代理优先,VIF 为补充的方式接管系统请求。这样做有几个好处:
- 代理模式接管时,App 和 Surge 间使用的是 loopback socket 通讯,由于不需要在 userspace 进行 TCP 重组装,代理接管模式比 VIF 模式更高效。
- 当请求通过 HTTP 代理模式被接管时,说明这个请求一定是 HTTP/HTTPS 协议(HTTP CONNECT 模式下可能有些许例外)。这使得 Surge 可以直接使用 HTTP/MITM 引擎进行处理。而如果由 VIF 接管,则并没有方法绝对确认这是否是 HTTP/HTTPS 协议,只能靠端口号/数据包特征进行猜测。
- 使用 HTTP 引擎接管除了可以使用修改功能外,还可以使得 Surge 在建立向外的连接时,在连接建立阶段便发出客户端首个数据包,即 0-RTT,降低握手延迟。
但是越来越多的 App 开始检测系统代理设置并拒绝工作,这是一种既不专业也无必要的安全措施,一方面来说代理设置在一些大型企业中是一种很常见的配置,另一方面即使不设置代理,也可以通过 VIF 甚至上级路由劫持或修改流量。如果 App 在意流量安全,应该正确使用 Certificate Pinning 等安全手段,而非在代理设置上为难用户。
但是由于使用代理的用户量确实过少使得无法影响厂商决策,我们不得不进行妥协。Surge iOS 将调整为 VIF 接管优先的工作模式以绕过该问题。目前测试阶段将强制切换为该模式,之后将重新开放代理模式优先选项。如果某 app 在该版本后无法正常工作请反馈。
于此同时,还优化了 VIF 引擎的工作方式以应对该变化:
发往 80/443 端口的请求,会等待客户端发送第一个数据包后,判断是否为有效的 HTTP/TLS 请求决定处理方式,若非有效的 HTTP 请求,或 300ms 内未收到首个数据包,则回退至 TCP 转发模式。因此对于使用 80 端口的请求,不再需要配置 force-http-engine-hosts 参数。
将自动识别 TLS Client Hello 消息并提取 SNI,增加针对 SNI 的规则和 MITM 主机名匹配。
其他说明:
目前仅对 80/443 端口开启了协议自识别,因为部分协议是由服务端先发送数据,如 SSH、IMAP、FTP,等待客户端数据再进行后续工作的流程将对这些请求造成不必要的延迟。其余端口的 HTTP 请求若需要由 HTTP 引擎处理依然需要配置 force-http-engine-hosts。
MITM 依然需要配置主机名以开启,但是不再需要 tcp-connection 参数,将默认对 TCP 请求生效。
本次调整后,由于 VIF 接管的 HTTP/HTTPS 请求将自动由 HTTP 引擎处理,对比原来手动配置 VIF Only 兼容模式的方式,HTTP/HTTPS 请求的握手延迟会有所下降。(因为可以正确识别与构造 early data 完成 0-RTT 握手。原先仅在代理模式下支持)