Surge 原理与实现
为了方便各位购买了 Surge 的用户更好的理解 Surge 的功能,能够自己通过灵活修改配置以应对不同的需求,我写了这篇中文的 Surge 原理与实现供各位参考。
从 Surge 的几大核心组件分别说起吧:
1. Surge Proxy Server
这是 Surge 最核心的部分,用于处理所有的 HTTP/HTTPS 请求。用 Proxy 去处理请求而不是用 TUN,有很多原因,主要是因为 TUN 是工作在 IP Layer 的:
这是 Surge 中最复杂的组件,基本上等同于一个不带 cache 的 squid,其中的难点一方面是调度问题,另一方面是怎么样去判断一个 HTTP 请求是否完成(比如 chunked transfer encoding),本身 HTTP RFC 在这方面就有非常多的细节问题,再加上很多自制的 HTTP Server 不是特别的遵守规范,所以只能通过大量的时间去积累经验完成。
2. DNS Client
最早的版本中,Surge 也是使用 getaddrinfo 这类的系统调用去进行 DNS 解析的,但是后来越来越不能满足需求,所以就又造了个轮子,有这些好处:
这部分的功能差不多是个 mini 版本的 dnsmasq 吧。由于是自己实现的,以后要做 TCP DNS 或者非 53 端口的支持都是很简单的事。
3. Surge TUN Interface
最早的版本没有这个组件,但有部分应用使用的是 HTTP/HTTPS 以外的 TCP 协议 (如 SPDY、IMAP),没有遵从代理设置,因此无法被 Surge 接管流量。为了解决这个问题,才加入了这个组件。
核心原理就是通过一个 Surge 内部的 TCP stack,将 IP Packet 中的 TCP 数据提取出来,再重新用 Proxy 进行请求(或者直接连接对应的服务器),再将返回的数据重新封装成 IP Packet。
正如前面提到的,用 TUN 处理请求会有一些问题,最大的问题是,由 TUN Interface 处理的流量,DOMAIN 相关的 Rule 会无效,除非使用了 force-remote-dns 选项。
这是由 TCP/IP 协议的特性所决定的,App 会先发出一个 DNS question,获取要连接的服务器的 IP 地址,然后直接向这个 IP 地址发起连接,所以有了第 4 个组件。
4. IP Layer DNS Forwarder
这个组件配合 TUN Interface 使用,会将收到 DNS 的 IP Packet,进行简单改动后直接转发给 upstream DNS。
但是在转发前,该组件会检查需要解析的域名,是否匹配上了带有 force-remote-dns 选项的规则,如果是,不进行转发,直接返回一个 240.1.x.x 的 fake IP。当 TUN Interface 收到一个发往 240.1.x.x 的包的时候,反向查出真正的域名是什么,然后直接以域名的形式转交给 Proxy,避免本地的 DNS 查询动作。
force-remote-dns 选项主要是为了解决有些域名在本地查询会有障碍的问题(如公司内网域名),然而因为返回了一个 fake IP,且 Surge 没有权限去强制清除系统或者应用的 DNS cache,所以在 Surge 关闭后可能导致一些问题,所以请谨慎的只给确实需要的域名开启这个选项。
其余还有一系列的 homemade 小组件(如各个协议的 client),就不一一描述了,之后想到什么再补充。
所以,看起来 $9.99 超值吧(大雾)