HTTPS相关优化手段
HTTPS连接大致上可以划分为两个部分,第一个是建立连接时的非对称加密握手,第二个是握手后的对称加密报文传输。
HTTPS比HTTP增加了一个TLS握手的步骤,这个步骤最长可以花费两个消息往返,也就是2-RTT。而且在握手消息的网络延时消耗外,还会有其他的一些“隐形”消耗,比如:
- 产生用于**交换的临时公私钥对(ECDHE);
- 验证证书时访问CA获取CRL或者OCSP;
- 非对称加密解密处理“Pre-Master”。
如下图标识出来部分影响性能的部分:
硬件优化
HTTPS连接是计算密集型,而不是I/O密集型。所以,如果你花大价钱去买网卡、带宽、SSD存储就是“南辕北辙”了,起不到优化的效果。
- 选择更快的CPU,最好还内建AES优化,这样即可以加速握手,也可以加速传输
- 可以选择“SSL加速卡”,加解密时调用它的API,让专门的硬件来做非对称加解密,分担CPU的计算压力。
- SSL加速服务器:用专门的服务器集群来彻底“卸载”TLS握手时的加密解密计算,性能自然要比单纯的“加速卡”要强大的多。
软件优化
一个是软件升级,一个是协议优化。
- 软件升级: 比如把Linux内核由2.x升级到4.x,把Nginx由1.6升级到1.16,把OpenSSL由1.0.1升级到1.1.0/1.1.1。
协议优化
- 如果有可能,应当尽量采用TLS1.3,它大幅度简化了握手的过程,完全握手只要1-RTT,而且更加安全。
- 椭圆曲线也要选择高性能的曲线,最好是x25519,次优选择是P-256。对称加密算法方面,也可以选用“AES_128_GCM”,它能比“AES_256_GCM”略快一点点。
- 在Nginx里可以用“ssl_ciphers”“ssl_ecdh_curve”等指令配置服务器使用的密码套件和椭圆曲线,把优先使用的放在前面,例如:
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:EECDH+CHACHA20;
ssl_ecdh_curve X25519:P-256;
证书优化
除了**交换,握手过程中的证书验证也是一个比较耗时的操作,服务器需要把自己的证书链全发给客户端,然后客户端接收后再逐一验证。
这里就有两个优化点,一个是证书传输,一个是证书验证。
使用OCSP(在线证书状态协议): 向CA发送查询请求,让CA返回证书的有效状态。
但是OCSP需要多发出一次网络请求的消耗,还要依赖于CA服务器,如果CA服务器很忙,那响应也是等不起的。
OCSP Stapling(OCSP装订): 可以让服务器预先访问CA获取OCSP响应,然后在握手时随着证书一起发送给客户端,免去了客户端连接CA服务器查询的时间。
会话复用
在HTTPS建立连接的过程中。显示三次TCP握手,然后是TLS一次握手,这后一次握手的重点是算出主**“Master Secret”。而主**每次连接都要重新计算,未免有点太浪费了,如果能够把“辛辛苦苦”算出来的主**缓存一下“重用”,不就可以免去握手和计算的成本了。
会话复用分为两种:第一种“Session ID”: 就是客户端和服务器首次连接后各自保存一个会话的ID号,内存里存储主**和其他相关的信息。当客户端再次连接时发一个ID过来,服务器就在内存里找,找到就直接用主**恢复会话状态,跳过证书验证和**交换,只用一个消息往返就可以建立安全通信。
如下图所示,在会话复用中,服务器在“ServerHello”消息后直接发送了“Change Cipher Spec”和“Finished”消息,复用会话完成了握手。
会话票证
“Session ID”是最早出现的会话复用技术,也是应用最广的,但它也有缺点,服务器必须保存每一个客户端的会话数据,对于拥有百万、千万级别用户的网站来说存储量就成了大问题,加重了服务器的负担。
于是出现,第二种“Session Ticket”方案。
它有点类似HTTP的Cookie,存储的责任由服务器转移到了客户端,服务器加密会话信息,用“New Session Ticket”消息发给客户端,让客户端保存。
不过“Session Ticket”方案需要使用一个固定的**文件(ticket_key)来加密Ticket,为了防止**被**,保证“前向安全”,**文件需要定期轮换,比如设置为一小时或者一天。
预共享**
“False Start”“Session ID”“Session Ticket”等方式只能实现1-RTT,而TLS1.3更进一步实现了“0-RTT”,原理和“Session Ticket”差不多,但在发送Ticket的同时会带上应用数据(Early Data),免去了1.2里的服务器确认步骤,这种方式叫“Pre-shared Key”,简称为“PSK”。
但“PSK”也不是完美的,它为了追求效率而牺牲了一点安全性,容易受到“重放攻击”(Replay attack)的威胁。黑客可以截获“PSK”的数据,像复读机那样反复向服务器发送。
解决的办法是只允许安全的GET/HEAD方法,在消息里加入时间戳、“nonce”验证,或者“一次性票证”限制重放。
参考资料
以上内容参考极客时间《透视HTTP协议》课程