TLS 协议由于承担了一项额外的功能,需要验证目标服务器身份,导致其握手时会比较复杂。
ping 的时间表示,一个 IP 层数据包从本地发出,到服务器再返回的来回时间,即 RTT(round-trip time**)。**
在发起代理连接时,首先我们需要进行 TCP 3 次握手,耗时为 1 个 RTT。(此处把最后的 ACK 直接并入后续的数据传输部分)。
然后进行 TLS 握手,因为服务端和客户端需要进行身份验证并协商协议版本号、加密方式等细节,第一次连接时需要 2 个 RTT。当然 TLS 的制定者也发现这太慢了,于是引入了 TLS Session Resumption,当服务端和客户端服务器连接过一次后,之后的连接可以直接复用先前的协商结果,使得 RTT 降低到 1 个 RTT。但这需要服务器和客户端的支持。(这是为什么 Surge benchmark 时,对于 TLS 代理第一次的测试结果可能较慢的原因之一)
对于 HTTPS 协议,当 TLS 连接建立后,客户端通过 HTTP 层发起代理请求,服务端回应连接建立,此后进入正常的代理通讯环节,再耗费 1 个 RTT。
对于 SOCKS5-TLS 协议,当 TLS 连接建立后,如果没有验证的环节,那么需要再耗费 1 个 RTT,如果有验证(用户名密码),那么需要耗费 2 个 RTT。
而对于 shadowsocks,由于使用的是预共享密钥(pre-shared key, PSK),加密方式也是预先约定好的,所以不需要进行协商,只需要在 TCP 建立之后,再耗费一个 1 个 RTT 告知目标主机名。
总结如下:
HTTPS(TLS Session Resumption):3 个 RTT
SOCKS5-TLS 无验证:3 个 RTT
SOCKS5-TLS 有验证:4 个 RTT
shadowsocks:2 个 RTT
(注:最后一个 RTT 并不严谨,因为客户端可以在最后一个 RTT 产生响应前,直接开始后续传输。另外如果使用了 TCP Fast Open,可以看作 TCP 阶段 RTT 为 0。)
对于日常使用,最影响性能的就是握手速度,后续传输过程中的加解密性能,对于现代 CPU 来说基本都不会构成瓶颈。 shadowsocks 由于有 PSK 的特点,在 TCP 协议基础上已经达到极限,不可能有协议能再低于 2 个 RTT。
所以,同等网络环境下,shadowsocks 是明显快于 HTTPS 的。(体现在延迟上,而不是带宽)
另外,最新的 TLS 1.3 协议正力图解决这个问题,由于目前还处于草案阶段,各种工具链不完善,现在不太好评估实际效果。