【HTTPS】HTTPS如何优化?

由裸数据传输的HTTP协议转成加密数据传输的HTTPS协议,给应用数据套了个保护伞,提高安全性的同时也带来了性能消耗。

因为HTTPS相比HTTP协议多一个TLS协议握手过程,目的是为了通过非对称加密握手协商或者交换出对称加密密钥,这个过程最长可以花费掉2RTT,接着后续传输的应用数据都得使用加密密钥来加密/解密。

为了数据的安全性,我们不得不使用HTTPS协议,至今大部分网址都已从HTTP迁移至HTTPS协议,因此针对HTTPS的优化是非常重要的。

这次,就从多个角度来优化HTTPS。


分析性能损耗

既然要对HTTPS优化,那得清楚哪些步骤会产生性能消耗,在对症下药。

产生性能消耗的两个环节:

  • 第一个环节,TLS协议握手过程;
  • 第二个环节,握手后的对称加密报文传输。

对于第二个环节,现在主流的对称加密算法AES/ChaCha20性能都是不错的,而且一些CPU厂商还针对它们做了硬件级别的优化,因此这个环节的性能消耗可以说非常的小。

而第一个环节,TLS协议握手过程不仅增加了网络延时(最多2RTT左右),而且握手过程中的一些步骤也会产生性能损耗,比如:

  • 对于ECDHE密钥协商算法,握手过程中客户端和服务端都需要临时生成椭圆曲线公私钥;
  • 客户端验证证书是,会访问CA获取CRL或者OCSP,目的是验证服务的证书是否有被吊销;
  • 双方计算Pre-Master,也就是对于加密密钥。

硬件优化

对于计算机,软件都是跑在物理硬件上,硬件越越好,软件跑的也越快,所以如果要优化HTTPS优化,那就是优化硬件。

HTTPS协议是极端密集型,而不是I/O密集型,所以,应该提升CPU硬件。

一个好的CPU,可以提高计算性能,因为HTTPS连接过程中就由大量需要计算密钥的过程,所以这样可以加速TLS握手过程。

另外,如果可以,应该选择可以支持AES-NI特性的CPU,因为这种款式的CPU能在指令级别优化了AES算法,这样便可以加速数据的加解密传输过程。

如过我们的CPU支持AES_NI特性,那么对于对称加密的算法应该选择AES算法。否则可以选择ChaCha20对称加密算法,因为ChaCha20算法的运算指令相比AES换发会对CPU更友好一点。

软件优化

软件优化方向可以分为两种,一种是软件升级,一个是协议优化。

软件升级就是将正在使用的软件升级到最新版本,因为最新版本不仅提高了最新的特性,也优化了以前软件的问题或性能。

看似简单的软件升级,对于有成百上千服务器的公司来说,软件升级也跟硬件升级童谣是一个棘手的问题,因为要实行软件升级,会花费时间和人力,同时也存在一定的风险,也可能会影响正常的线上服务。

我们还可以进行协议优化,也就是在现有的环节下,通过较小的改动,来进行优化。

协议优化

协议的优化就是对密钥交换过程进行优化。

密钥交换算法优化

TLS1.2版本如果使用的是RSA密钥交换算法,那么需要4次握手,也就是要花费2RTT,才可以进行应用数据的传输,而且RSA密钥交换算法不具备前向安全性。

总之使用RSA密钥交换算法的TLS握手过程,不仅慢,而且安全性也不高。

因此如果可以,尽量选用ECDHE密钥交换算法替换RSA算法,因为该算法支持False Start ,它是抢跑的意思,客户端可以在TLS协议的第三次握手后,第四次握手前,发送加密的应用数据,一次将TLS握手的消息往返由2RTT减少到1RTT,而且安全性也高,具备前向安全性。

ECDHE算法是基于椭圆曲线实现的,不同的椭圆曲线性能也不高,应该尽量选择x25519曲线,该曲线是目前最快的椭圆曲线。

在对称加密算法方面,如果对安全性不是特别高的要求,可以选用AES_128_GCM,它比AES_256_GCM快一些,因为密钥的长度短一些。

比如在Nginx上,可以使用ssl_ciphers指令配置想使用的非对称加密算法和对称加密算法,也就是密钥套件,而且把性能最快最安全的算法放在最前面。

TLS升级

如果可以,直接把TLS1.2成绩成TLS1.3, TLS1.3大幅度简化了握手的步骤,完成TLS握手只要1RTT,而且安全性更高。

在TLS1.2的握手中,一般是需要4次握手,先要通过Client hello(第1次握手)和Server Hello(第2次握手)消息协商出后续使用的加密算法,在互相交换公钥(第3和第4次握手),然后计算出最终的会话密钥。

可以发现TLS1.3把Hello和公钥交换这两个消息合并成了一个消息,于是这样就减少到主要1RTT就能完成TLS握手。

如何合并呢?具体的做法是,客户端在Client Hello消息里带上了支持的椭圆曲线,以及这些椭圆曲线对应的公钥。

服务端收到后,选定一个椭圆曲线等参数,然后返回消息时,带上服务端这边的公钥。经过这1个RTT,双方手上已经有生成会话密钥的材料了,于是客户端计算出会话密钥,就快出进行应用数据的加密传输了。

而且,TLS1.3对密码太监进行“减肥”了,对于密钥交换算法,飞出了不支持前向安全性的RSA和DH算法,只支持ECDHE算法。

对于对称加密和签名算法,只支持目前最安全的几个密码套件,比如openssl中仅支持下面5中密码套件:

  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256
  • TLS_AES_128_GCM_SHA256
  • TLS_AES_128_CCM_8_SHA256
  • TLS_AES_128_CCM_SHA256

之所以TLS1.3仅支持这么少的密码套件,是因为TLS1.2由于支持各种古老不安全的密码套件,中间人可以利用降级攻击,伪造客户端的Client Hello消息,替换客户端支持的密码套件为一些不安全的密码套件,使得服务器被迫使用这个密码套件进行HTTPS连接,从而破解密文。

证书优化

为了验证服务器的身份,服务器会在TLS握手过程中,把自己的证书发给客户端,一次证明自己身份是可信的。

对于证书的优化,可以有两个方向:

  • 一个是证书传输,
  • 一个是证书验证

证书传输优化

要让证书更便于传输,那必然是减少证书的大小,这样可以节约带宽,也能减少客户端的运算量。所以,对于服务器的证书应该选择椭圆曲线(ECDSA)证书,而不是RSA证书,因为在相同安全强度下,ECC密钥长度比RSA短的多。

证书验证优化

客户端在验证证书时,是个复杂的过程,会走证书链逐级验证,验证的过程不仅需要用CA公钥解密证书以及用签名算法验证证书的完整性,而且为了知道证书是否被CA吊销,客户端优势还会再去访问CA,下载CRL或者OCSP数据,以此确认证书的有效性。

这个访问过程是HTTP访问,因此又会产生一系列网络通信的开销,如DNS查询、建立连接、收发数据等。

CRL

CRL称为证书吊销列表,这个列表是由CA定期更新,列表内容都是被撤销信任的证书序号,如果服务器的证书在此列表,就认为证书已经失效,不在的话,则认为证书是有效的。

但是CRL存在两个问题:

第一个问题,由于CRL列表是由CA维护的,定期更新,如果一个证书刚被吊销后,客户端在更新CRL之前耗时会信任这个证书,实时性较差;

第二个问题,随着吊销证书的增多,列表会越来越大,下载的速度就会越慢,下载问客户端还得遍历这么大的列表,那么就会导致客户端在校验证书这一环节的延时很大,进而拖慢了HTTPS连接。

OCSP

因此你,现在基本都是使用OCSP(Online Certificate Status Protocol),名为在线证书状态协议来查询证书的有效性,它的工作方式的是向CA发送查询请求,让CA返回证书的有效状态。

不必像CRL方式一样,客户端需要下载大大的列表,好药从列表查新,同时因为可以实时查询每一张证书的有效性,解决了CRL的实时性问题。

OCSP需要向CA查询,因此也是要发生网络请求,如果网络状态不好,或者CA服务器繁忙,也会导致客户端在校验证书这一环节的延时变大。

OCSP stapling

于是为了解决这一个网络开销,就出现了OCSP Stapling,其原理是:服务器向CA周期性地查询证书状态,获得一个带有时间戳和签名的响应加过并缓存它。

当有客户端发起连接请求时,服务器会把这个响应结果在TLS握手过程中发给客户端。由于有签名的存在,服务器无法篡改,因此客户端佳能得知证书是否已被吊销了,这样客户端就不需要再去查询。

会话复用

TLS握手的目的就是为了协商出会话秘钥,也就是对称加密密钥,那我们如果把首次TLS握手协商的对称加密密钥缓存起来,待下次需要建立HTTPS连接时,直接复用这个密钥,不就减少TLS握手的性能损耗了么?

这种方式就是会话复用,会话复用分两种:

  • 第一种叫Session ID;
  • 第二种叫Session Ticket;

Session ID

Session ID的工作原理是,客户端和服务器首次TLS握手连接后,双方会在内存缓存会话密钥,并用唯一的Session ID来标识,Session ID会话密钥相当于key-value的关系。

当客户端再次连接时,hello消息会带上Session ID,服务器收到后就会从内存找,如果找到就直接用该会话密钥恢复会话状态,跳过其余的过程,只用一个消息往返就可以建立安全通信,当然为了安全性,内存中的会话密钥会定期失效。

但是它有两个缺点:

  • 服务器必须保持每一个客户端的会话秘钥,随着客户端的增多,服务器的内存压力也会越大。
  • 现在网站服务一般是有多台服务器通过负载均衡提供服务的,客户端再次连接不一定会命中上次访问过的服务器,于是还要走完整的TLS握手过程。

Session Ticket

为了解决Session ID的问题,就出现了Sesion Ticket,服务器不再缓存每个客户端的会话密钥,而是把缓存的工作交给了客户端,类似于HTTP的Cookie。

客户端与服务器首次建立连接时,服务器会加密会话密钥作为Ticket发给客户端,交给客户端缓存该Ticket。

客户端再次连接服务器时,客户端会发送Ticket,服务器加密后就可以获取上一次的会话密钥,然后验证有效期,如果没问题,就可以恢复会话了,开始加密通信。

对于集群服务器的话,要确保每台服务器加密会话密钥的密钥是一致的,这样客户端携带Ticket访问任意一台服务器时,都能恢复会话。

SessionId和Session Ticket都不具备前向安全性,因为一旦加密会话密钥的密钥被破解或者服务器泄漏会话密钥,前面劫持的通信密文都会被破解。

同时应对重放击也很困难,这里简单介绍下重防攻击工作的原理。

假设Alice想向Bob证明自己的身份,Bob要求Alice的密码作为身份证明,Alice应尽全力提供(可能是在经过如哈希函数的转换之后)。与此同时,Eve 窃听了对话并保留了密码(或哈希)。

交换结束后,Eve(冒充 Alice )连接到 Bob。当被要求提供身份证明时,Eve 发送从 Bob 接受的最后一个会话中读取的 Alice 的密码(或哈希),从而授予 Eve 访问权限。

重放攻击的危险之处在于,如果中间人截获了某个客户端的 Session ID 或 Session Ticket 以及 POST 报文,而一般 POST 请求会改变数据库的数据,中间人就可以利用此截获的报文,不断向服务器发送该报文,这样就会导致数据库的数据被中间人改变了,而客户是不知情的。

避免重放攻击的方式就是需要对会话密钥设定一个合理的过期时间

Pre-shared Key

前面的Session ID和Session Ticket方式都需要在1RTT才能恢复会话。

而TLS1.3 更为厉害,对于重连TLS1.3只需要0RTT,原理和Ticket类似,只不过在重连时,客户端会把Ticket和HTTP请求一同发送给服务器,这种服务器叫Pre-shared KEY。

同样的,pre-shared Key也有重放攻击的危险。

如上图,假设中间人通过某种方式,截获了客户端使用会话重用技术的 POST 请求,通常 POST 请求是会改变数据库的数据,然后中间人就可以把截获的这个报文发送给服务器,服务器收到后,也认为是合法的,于是就恢复会话,致使数据库的数据又被更改,但是此时用户是不知情的。

所以,应对重放攻击可以给会话密钥设定一个合理的过期时间,以及只针对安全的 HTTP 请求如 GET/HEAD 使用会话重用。

总结

对于硬件优化的方向,因为HTTPS是属于计算密集型,应该选择计算力更强的CPU,而且最好选择支持AES-NI特性的CPU,这个特性可以在硬件级别优化AES对称加密算法,加快应用数据的加解密。

对于软件优化的方向,如果可以,把软件升级成较新的版本,比如将Linux内核2.x升级成4.x,将openssl1.0.1升级到1.1.1,因为新版本的软件不仅会提供新的特性,而且还会修复老版本的问题。

对于协议优化的方向:

  • 密钥交换算法应该选择ECDHE算法,而不用RSA算法,因为ECDHE算法具备前向安全性,而且客户端可以在第三次握手之后,就发送加密应用数据,节省了1RTT。
  • 将TSL1.2升级TSL1.3,因为TSL1.3的握手过程只需要1RTT,而且安全性更强。

对于证书优化的方向:

  • 服务器应该选用ECDSA证书,而非RSA证书,因为在相同安全级别下,ECC的密钥长度比RSA段很多,这样可以提高证书传输的效率;
  • 服务器应该开启OCSP Stapling功能,有服务器预先获得OCSP的响应,并把响应结果缓存起来,这样TLS握手的时候就不用再访问CA服务器,减少了网络通信的开销,提高了证书验证的效率。

对于重连HTTPS是,我们可以使用一些技术让客户端和服务端使用上一次HTTPS连接使用的会话密钥,直接恢复会话,而不用在重新走完整的TLS握手过程。

常见的会话重用技术有Session ID和Session Ticket,用了会话重用技术,当再次重连HTTS是,只需要1RTT就可以恢复会话,对于TLS1.3使用Pre-Shared Key会话重用技术,只需要0RTT就可以恢复会话。

这些会话重用技术虽然好用,但是存在一定的安全风险,他们不仅不具备前向安全,而且有重放攻击的风险,所以应当对会话密钥设定一个合理的过期时间。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值