3、HTTPS对速度和性能的影响
既然HTTPS非常安全,数字证书费用也不高,那为什么互联网公司不全部使用HTTPS呢?原因主要有两点:
HTTPS对速度的影响非常明显。每个HTTPS连接一般会增加1-3个RTT,加上加解密对性能的消耗,延时还有可能再增加几十毫秒。
HTTPS对CPU计算能力的消耗很严重,完全握手时,web server的处理能力会降低至HTTP的10%甚至以下。
下面简单分析一下这两点。
3.1 HTTPS对访问速度的影响
我用一张图来表示一个用户访问使用HTTPS网站可能增加的延时:
HTTPS增加的延时主要体现在三个阶段,包含了上图所示的2和3阶段。
● 302跳转。为什么需要302?因为用户懒。我想绝大部分网民平时访问百度时都是输入 www.baidu.com 或者baidu.com吧?很少有输入 http://www.baidu.com 访问百度搜索的吧?至于直接输入 https://www.baidu.com 来访问百度的HTTPS服务的就更加少了。所以为了强制用户使用HTTPS服务,只有将用户发起的HTTP请求www.baidu.com302 成 https://www.baidu.com 。这无疑是增加一个RTT的跳转延时。
● 上图第三阶段的SSL完全握手对延时的影响就更加明显了,这个影响不仅体现在网络传输的RTT上,还包含了数字签名的校验,由于客户端特别是移动端的计算性能弱,增加几十毫秒的计算延时是很常见的。
● 还有一个延时没有画出来,就是证书的状态检查,现在稍微新一点的浏览器都使用ocsp来检查证书的撤销状态,在拿到服务器的证书内容之后会访问ocsp站点获取证书的状态,检查证书是否撤销。如果这个ocsp站点在国外或者ocsp服务器出现故障,显然会影响这个正常用户的访问速度。不过还好ocsp的检查周期一般都是7天一次,所以这个对速度的影响还不是很频繁。 另外chrome默认是关闭了ocsp及crl功能,最新版的firefox开启了这个功能,如果ocsp返回不正确,用户无法打开访问网站。
实际测试发现,在没有任何优化的情况下,HTTPS会增加200ms以上的延时。
那是不是对于这些延时我们就无法优化了呢?显然不是,部分优化方式参考如下:
1、服务器端配置HSTS,减少302跳转,其实HSTS的最大作用是防止302 HTTP劫持。HSTS的缺点是浏览器支持率不高,另外配置HSTS后HTTPS很难实时降级成HTTP。
2、设置ssl session 的共享内存cache. 以nginx为例,它目前只支持session cache的单机多进程共享。配置如下:
ssl_session_cache shared:SSL:10m;
如果是前端接入是多服务器架构,这样的session cache是没有作用的,所以需要实现session cache的多机共享机制。我们已经在nginx 1.6.0版本上实现了多机共享的session cache。多机session cache的问题必须要同步访问外部session cache,比如redis。由于openssl目前提供的API是同步的,所以我们正在改进openssl和nginx的异步实现。
3、配置相同的session ticket key,部署在多个服务器上,这样多个不同的服务器也能产生相同的 session ticket。session ticket的缺点是支持率不广,大概只有40%。而session id是client hello的标准内容,从SSL2.0开始就被全部客户支持。
ssl_session_tickets on;
ssl_session_ticket_key ticket_keys;
4、设置ocsp stapling file,这样ocsp的请求就不会发往ca提供的ocsp站点,而是发往网站的webserver。ocsp的配置和生成命令如下:
● ssl_stapling on;
● ssl_stapling_file domain.staple;
● 上面是nginx配置,如下是ocsp_stapling_file的生成命令:
● openssl s_client -showcerts -connect yourdomain:443 < /dev/null | awk -v c=-1 '/-----BEGIN CERTIFICATE-----/{inc=1;c++} inc {print > ("level" c ".crt")} /---END CERTIFICATE-----/{inc=0}'
● for i in level?.crt;
● do
● openssl x509 -noout -serial -subject -issuer -in "$i";
● echo;
● done
● openssl ocsp -text -no_nonce -issuer level1.crt -CAfile CAbundle.crt -cert level0.crt -VAfile level1.crt -url $ocsp_url -respout domain.staple ,其中$ocsp_url等于ocsp站点的URL,可以通过如下命令求出:for i in level?.crt; do echo "$i:"; openssl x509 -noout -text -in "$i" | grep OCSP; done,如果是证书链,一般是最底层的值。
5、优先使用ecdhe密钥交换算法,因为它支持PFS( perfect forward secrecy) ,能够实现 false start 。
6、设置tls record size,最好是能动态调整record size,即连接刚建立时record size设置成msg,连接稳定之后可以将record size动态增加。
7、如果有条件的话可以启用tcp fast open。虽然现在没有什么客户端支持。
8、启用SPDY。SPDY是强制使用HTTPS的,协议比较复杂,需要单独的文章来分析。可以肯定的一点是使用SPDY的请求不仅明显提升了HTTPS速度,甚至比HTTP还要快。在无线WIFI环境下,SPDY比HTTP要快50ms左右,3G环境下比HTTP要快250ms。
3.2 HTTPS 对性能的影响
HTTPS为什么会严重降低性能?主要是握手阶段时的大数运算。其中最消耗性能的又是密钥交换时的私钥解密阶段(函数是rsa_private_decryption)。这个阶段的性能消耗占整个SSL握手性能消耗的95%。
前面提及了openssl密钥交换使用的算法只有四种:rsa, dhe, ecdhe,dh。dh由于安全问题目前使用得非常少,所以这里可以比较下前面三种密钥交换算法的性能,具体的数据如下:
上图数据是指完成1000次握手需要的时间,显然时间数值越大表示性能越低。图片和测试方法都可以参考原文,地址如下: http://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy.html 。
密钥交换步骤是SSL完全握手过程中无法绕过的一个阶段。我们只能采取如下措施:
● 通过session cache和session ticket提升session reuse率,减少完全握手(full handshake)次数,提升简化握手(abbreviated handshake)率。
● 出于前向加密和false start的考虑,我们优先配置ecdhe用于密钥交换,但是性能不足的情况下可以将rsa配置成密钥交换算法,提升性能。
openssl 自带的工具可以计算出对称加密、数字签名及HASH函数的各个性能,所以详细数据我就不再列举,读者可以自行测试 。
结论就是对称加密RC4的性能最快,但是RC4本身不安全,所以还是正常情况下还是采用AES。HASH函数MD5和SHA1差不多。数字签名是ecdsa算法最快,但是支持率不高。
事实上由于密钥交换在整个握手过程中消耗性能占了95%,而对称加解密的性能消耗不到0.1%,所以server端对称加密的优化收益不大。相反,由于客户端特别是移动端的CPU计算能力本来就比较弱,所以对称加密和数字签名的优化主要是针对移动客户端。
poly1350 是google推出的号称优于aes-gcm的对称加密算法,适用于移动端,可以试用一下。
最后经过测试,综合安全和性能的最优cipher suite配置是: ECDHE-RSA-AES128-GCM-SHA256.
如果性能出现大幅度下降,可以修改配置,提升性能但是弱化了安全性,配置是:rc4-md5,根据openssl的规则,密钥交换和数字签名默认都是使用rsa。
(责任编辑:安博涛)