首页 > 其他分享 >HTTPS 性能优化技巧

HTTPS 性能优化技巧

时间:2023-11-27 10:38:11浏览次数:40  
标签:TLS 技巧 RSA HTTPS ECDHE 优化 CPU 服务端 客户端

认识SSL/TLS

SSL和TLS都是用于保障端到端之间连接的安全性。SSL最初是由Netscape开发的,后来为了使得该安全协议更加开放和自由,更名为TLS,并被标准化到RFC中,现在主流的是TLS 1.2版本。

HTTPS 性能优化技巧HTTPS 性能优化技巧

从上图,可以看出SSL/TLS是介于应用层和传输层之间,并且分为握手层(Handshake Layer)和记录层(Record Layer)。

  • 握手层:端与端之间协商密码套件、连接状态。
  • 记录层:对数据的封装,数据交给传输层之前,会经过分片-压缩-认证-加密。
算法选择

TLS中可被配置的算法分类:

  1. 数字签名:RSA、DSA
  2. 流加密:RC4
  3. 分组加密:DES、AES
  4. 认证加密:GCM
  5. 公钥加密:RSA
  6. 消息认证码:SHA
  7. 密钥交换:Diffie–Hellman

密码套件决定了会使用到的算法,例如执行“openssl ciphers -v 'ALL' | grep ECDHE-RSA-AES128-GCM-SHA256”:

ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(128) Mac=AEAD

表明该算法是在TLS 1.2中支持的,密钥交换采用ECDH(EC是指采用椭圆曲线的DH),数字签名采用RSA,加密采用128位密钥长度的AESGCM,消息认证码采用AEAD(AEAD是一种新的加密形式,把加密和消息认证码结合到一起,而不是某个算法,例如使用AES并采用GCM模式加密,就能够为数据提供保密性、完整性的保障)。
如何理解完整性?
A 将明文M加密后为MC,发给B,B解密,得到明文。 如果此时有中间人C,将MC替换为CMC(虽然C不知道A怎么加密的,但这没关系),B将CMC解密,得到明文(那么B拿到的其实是错误的明文)。 所以需要引入消息认证码,B才能够判断收到的密文是否被篡改过。 这里你可能会问:那如果C同时伪造消息认证码呢? 这个就得看MAC和加密是如何配合的了,详情可以查看认证加密中的Approaches to Authenticated Encryption章节。

在TLS握手和数据传输的不同阶段会采用相应的算法:

  • 服务端身份验证:数字签名(RSA、ECDSA)
  • 密钥交换:RSA/密钥交换算法(ECDH)
  • 加密/解密:流加密(RC4)和分组加密(3DES/AES/AESGCM)
  • 生成消息认证码:SHA/AEAD

不知是否有人发现并没有提到压缩算法,如果google下TLS压缩优化相关的内容,会发现没有,因为目前在TLS 1.2 RFC中,关于压缩方法的结构定义为enum { null(0), (255) } CompressionMethod;,即只有null方法(不进行压缩)。目前存在对TLS压缩的攻击,可能是基于此原因,TLS压缩目前只是个概念性的东西,没有被真正应用起来。

如何选择算法——安全性

通常加密算法的安全性依赖于密钥的长度,且不同加密算法,即使密钥长度相同,但提供的安全性也可能是不同的,相关资料:key size。所以并没有一个标准的归一化方法去衡量所有的加密算法,但是有来自世界上各个组织/机构对不同类型算法安全性的评估,可以看下这个网站:https://www.keylength.com/。

执行“openssl ciphers -v 'ALL' | wc -l”会发现有100+个密码套件(不同openssl版本提供的密码套件有点差异),然而,实际只会使用到其中一部分,因为openssl提供的不少算法是不安全的,需要排除掉。

执行“openssl ciphers -v 'HIGH MEDIUM !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !CAMELLIA !IDEA !SEED !RC4' | wc -l”,发现只剩下50+个密码套件。

筛选后剩下的密码套件还是挺多的,一个个做性能测试的话,会GG的= =。其实可以根据需要支持的客户端,再筛选出主流的密码套件。网址:https://www.ssllabs.com/ssltest/clients.html,提供了绝大部分客户端对TLS的支持情况,点击相应的User agent可以查看到其支持的密码套件,并且各套件的安全性也被标注出来了。

网址:https://www.ssllabs.com/ssltest/,可以用于测试服务器的SSL配置情况,并会给出得分,如下图google的得分为A:

HTTPS 性能优化技巧HTTPS 性能优化技巧

如何选择算法——性能

以下性能测试都是选取主流的算法进行。

数字签名:ECDSA vs RSA

需要先分别生成采用ECDSA和RSA的签名证书。

生成ECDSA自签名的证书:

openssl ecparam -name prime256v1 -genkey -out ec_key.pem
openssl req -new -x509 -key ec_key.pem -out cert.pem -days 365

-param_enc参数使用默认的named_curve就可以了,如果使用explicit,会发现生成的证书nginx能配置成功,但客户端连接时会出现handshake error。
生成RSA签名的证书:

openssl req -newkey rsa:2048 -nodes -keyout rsa_key.pem -x509 -days 365 -out cert.pem

执行openssl speed rsa2048 ecdsap256测试下:

                  sign    verify    sign/s verify/s
rsa 2048 bits 0.000834s 0.000024s   1198.9  41031.9
                              sign    verify   sign/s  verify/s
256 bit ecdsa (nistp256)   0.0000s   0.0001s  21302.5   9728.5

可以看到签名性能ECDSA > RSA,而验证性能RSA > ECDSA。

测试环境:

  • 服务端:1台虚拟机CentOS 4核 openresty 2个worker
  • 客户端:4台虚拟机CentOS 4/2/2/2核(手头只有这些虚拟机= =), 用shell脚本模拟并发的ab -c 800 -n 800(并发的ab实例数=2*CPU_NUM),使用time命令获取消耗的时间
  • 测试页面562字节,目标是测试数字签名的性能,所以页面小点,避免加密/解密、数据传输占用太多时间

多台客户端如何同时启动?ctrl+tab,命令+回车……
为什么不用jmeter?我用了1Master3Slave的jmeter分布式压测发现,jmeter对于在该场景(CPU bound)下的性能测试不行,服务端压力上不去。
在相同的请求量下,RSA签名会使服务端CPU占用更高,所以这次测试需要在两种签名的压测下,服务端CPU都保持在90%以上(不然的话,对ECDSA就不公平了)。
为何openresty是2个worker?因为开4个的话,ECDSA的压测没法使openresty4个worker的CPU消耗达到90%。
ECDHE-ECDSA-AES128-GCM-SHA256,服务端CPU占比90%,结果:

客户端(CPU核数标识) 4 2 2 2
第一次 11.988 17.334 9.161 7.748
第二次 12.524 13.750 12.129 7.582
第三次 11.836 17.991 9.195 10.023
第四次 11.617 7.081 9.168 8.919

ECDHE-RSA-AES128-GCM-SHA256,服务端CPU占比100%,结果:

客户端(CPU核数标识) 4 2 2 2
第一次 12.704 21.088 18.232 6.134
第二次 13.355 21.071 26.990 6.102
第三次 14.638 16.009 11.669 6.071
第四次 13.913 21.061 21.271 5.108

从表格中的数据可以看出ECDSA的性能要比RSA好点,这里ECDSA的测试尚未压榨完服务端呢。从openssl speed的结果也可以看出ECDSA的签名性能是要远超过RSA的,而且签名是在服务端做的,所以面对海量的客户端,服务端应该选择使用ECDSA。

密钥交换:RSA vs ECDHE

测试环境同上,但只使用了4/2核两台客户端机器发请求。证书使用的是生成的RSA证书,ECDSA证书能用到的密钥交换算法只能是ECDHE。

AES256-GCM-SHA384,服务端CPU占比100%,结果:

客户端(CPU核数标识) 4 2
第一次 12.144 15.737
第二次 12.133 15.452
第三次 11.902 16.145
第四次 11.614 16.133

ECDHE-RSA-AES256-GCM-SHA384,服务端CPU占比100%,结果:

客户端(CPU核数标识) 4 2
第一次 11.950 16.213
第二次 12.488 16.666
第三次 12.167 16.378
第四次 13.784 16.484

从表格中的数据可以看出ECDHE与RSA的性能差不多。ECDHE比RSA要多了一次端到端的传输,还会用到RSA对DH参数进行签名和验证;而RSA密钥交换则会使用到RSA的加密/解密,具体可看如下CloudFlare的两张图,图片来自Keyless SSL: The Nitty Gritty Technical Details:
ECDHE支持前向保密(Forward Secrecy),简单理解:中间人可以保存下来客户端和服务端之间的所有通信数据,如果使用RSA握手,那么未来某一天,中间人如果获取到了服务端的私钥,就可以解密所有之前采集的通信数据了;如果采用ECDHE握手的话,就可以避免这个问题。而且使用ECDHE握手的话,还有可能开启TLS false start的特性(下文中会提到)。
RSA握手:

HTTPS 性能优化技巧HTTPS 性能优化技巧

ECDHE握手:

HTTPS 性能优化技巧HTTPS 性能优化技巧

所以密钥交换算法ECDHE会更好些。

对称加密:AES256-GCM vs AES256 vs AES128-GCM vs 3DES

测试环境同上,但只使用了4核一台客户端机器发请求,ab参数为 ab -n 2000 -c 10 ,ab实例4个,测试页面153K。因为是要压测对应用层数据的加密解密性能,所以连接数少,但每个连接的请求数多。

ECDHE-RSA-AES256-GCM-SHA384,服务端CPU占比94%,结果:

客户端(CPU核数标识) 4
第一次 17.972
第二次 18.863
第三次 18.761
第四次 19.345

ECDHE-RSA-AES256-SHA384,服务端CPU占比98%,结果:

客户端(CPU核数标识) 4
第一次 20.490
第二次 19.575
第三次 19.725
第四次 20.262

ECDHE-RSA-AES128-GCM-SHA256,服务端CPU占比92%,结果:

客户端(CPU核数标识) 4
第一次 17.886
第二次 18.449
第三次 17.897
第四次 18.371

DES-CBC3-SHA,服务端CPU占比100%,结果(太慢了,就测了两个=。=):

客户端(CPU核数标识) 4
第一次 52.262
第二次 51.476

从表格中的数据可以看出AES128GCM > AES256GCM > AES256 > 3DES。

消息认证码:SHA256 vs SHA1 vs AEAD

测试环境同上。

AES256-SHA256,服务端CPU占比100%,结果:

客户端(CPU核数标识) 4
第一次 18.544
第二次 18.309
第三次 18.594
第四次 18.670

AES256-SHA,服务端CPU占比98%,结果:

客户端(CPU核数标识) 4
第一次 15.418
第二次 15.071
第三次 16.614
第四次 16.146

AES256-GCM-SHA384,服务端CPU占比95%,结果:

客户端(CPU核数标识) 4
第一次 14.443
第二次 15.669
第三次 15.880
第四次 15.960

从结果中可以看出AES256-GCM-SHA384 > AES256-SHA > AES256-SHA256。

会话恢复

Session Cache

客户端希望恢复先前的session,或者复制一个存在的session,可以在ClientHello中带上Session ID,如果服务端能够在它的Session Cache中找到相应的Session ID的session-state(存储协商好的密码套件等信息),并且愿意使用该Session ID重建连接,那么服务端会发送一个带有相同Session ID的ServerHello。

HTTPS 性能优化技巧HTTPS 性能优化技巧

目前Nginx 只支持单机Session Cache,Openresty 支持分布式Session Cache,但处于实验阶段。

Session Ticket

Session Cache需要服务端缓存Session相关的信息,对服务端存在存取压力,而且还有分布式Session Cache问题。 对于支持Session Ticket的客户端,服务端可以通过某种机制将session-state加密后作为ticket发给客户端。客户端凭借该ticket就可以恢复先前的会话了。
类似于HTTP中用Json Web TOken作为cookie-session的另一种选择。
HTTPS 性能优化技巧HTTPS 性能优化技巧

OCSP(在线证书状态协议) stapling

当客户端在握手环节接受到服务端的证书时,除了对证书进行签名验证,还需要知道证书是否被吊销了,那么需要向证书中指定的OCSP url发送OCSP查询请求。

HTTPS 性能优化技巧HTTPS 性能优化技巧

对于同一份服务端证书,如果每个客户端都自己去查询一次证书状态就浪费了。所以,OCSP stapling就是为了解决这一问题,由服务端查询到证书状态(通常会缓存一段时间),并返回给客户端(客户端会在本地校验这个证书状态是否真实)。

HTTPS 性能优化技巧HTTPS 性能优化技巧

在nginx的配置中,可以选择性的配置是否对OCSP response做校验,防止将非法的证书状态发送给客户端。如果设置了校验,ssl_trusted_certificate参数需要为包含所有中间证书+根证书的文件。

如下图是对nginx请求OCSP Server的抓包,可以看到发了个http的ocsp请求:

HTTPS 性能优化技巧HTTPS 性能优化技巧

下图是对nginx在发送证书给客户端时,带上的证书状态的抓包:

HTTPS 性能优化技巧HTTPS 性能优化技巧

TLS缓冲区调优

nginx默认的ssl_buffer_size是16K(TLS Record Layer最大的分片),即一个TLS Record的大小,如果HTTP的数据是160K,那么就会被拆分为10个TLS Record(每个TLS Record会被TCP层拆分为多个TCP包传输)发送给客户端。

HTTPS 性能优化技巧HTTPS 性能优化技巧

如果TLS Record Size过大的话,拆分的TCP包也会较多,传输时,如果出现TCP丢包,整个TLS Record到达客户端的时间就会加长,客户端必须等待完整的TLS Record收到才能进行解密。

HTTPS 性能优化技巧HTTPS 性能优化技巧

如果TLS Record Size小一些的话,TCP丢包影响的TLS Record占比就会小很多,到达客户端的TLS Record就会多些,客户端干等着的时间就相对少了。但是,TLS Record Head的负载就增加了,可能还会降低连接的吞吐量。

假设ssl_buffer_size设置为1460byte:

HTTPS 性能优化技巧HTTPS 性能优化技巧

通常,在TCP慢启动的过程中,TLS Record Size小点好,因为这个时候TCP连接的拥塞窗口cwnd较小,TCP连接吞吐量也小。而在TCP连接结束慢启动之后,TLS Record Size就可以增大一些了,因为这个时候吞吐量上来了。所以更希望能够动态的调整nginx中ssl_buffer_size的大小,目前官方nginx还不支持,不过cloudflare为nginx打了个patch,以支持动态的调整TLS Record Size:Optimizing TLS over TCP to reduce latency。

TLS False Start

某一端在发送 Change Cipher Spec、Finished 之后,可以立即发送应用数据,无需等待另一端的 Change Cipher Spec、Finished 。这样,应用数据的发送实际上并未等到握手全部完成,从而节省出一个RTT时间。

完整握手时,Client Side False Start:

HTTPS 性能优化技巧HTTPS 性能优化技巧

简短握手时,Server Side False Start:

HTTPS 性能优化技巧HTTPS 性能优化技巧

Client Side False Start需要的条件:

  • 客户端和服务端都需要支持NPN/ALPN(浏览器要求)
  • 需要采用支持前向保密的密码套件,即使用ECDHE进行密钥交换(RFC7918中有规定)
其他优化
  • TCP优化,毕竟SSL数据也是基于TCP进行传输的
  • 证书优化,采用ECDSA证书、服务器发送给客户端的证书链包含所有中间证书
  • 硬件配置优化,例如使用SSL加速器
总结

本文是个人近段时间学习到的关于HTTPS性能优化的总结,推荐阅读HTTPS权威指南和High Performance Browser Networking以了解更多内容。

推荐的密码套件列表:

openssl ciphers -v 'ECDHE+ECDSA ECDHE AESGCM AES HIGH MEDIUM !kDH !kECDH !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !CAMELLIA !IDEA !SEED !RC4 !3DES'

其他额外的密码套件,比如需要支持IE6,可以放在密码套件列表末尾。

自己写了个go程序用于检测密码套件列表支持/不支持的客户端:sslciphersuitescheck

HTTPS 性能优化技巧HTTPS 性能优化技巧

 

本文地址:https://www.linuxprobe.com/https-performance-optimization.html

标签:TLS,技巧,RSA,HTTPS,ECDHE,优化,CPU,服务端,客户端
From: https://www.cnblogs.com/linuxprobe19/p/17848735.html

相关文章

  • .NET8 极致性能优化 Non-GC Heap
    前言.NET8里面JIT引入了一个新的机制,叫做Non-GCHeap。JIT可以确保相关对象分配在Non-GCHeap上,该堆像其名称一样,不受GC管理。JIT需要保证这个对象没有被GC引用,并且在这个对象的生命周期内一直是根对象(不会被GC消灭的对象)的状态。原文:.NET8极致性能优化Non-......
  • 性能优化的一般策略及方法
    性能优化的一般策略及方法在汽车嵌入式开发领域,性能优化始终是一个无法回避的问题:座舱HMI想要实现更流畅的人机交互通信中间件在给定的CPU资源下,追求更高的吞吐量更一般的场景:嵌入式设备CPU资源告急,需要降低CPU使用率...不同的工程师会从不同的角度给出不同的优化......
  • 微软RDP远程桌面优化
    微软RDP远程桌面优化介绍以下来自了解远程桌面协议(RDP)RDP基于T-120系列协议标准,并且是后者的扩展。支持多通道的协议允许单独的虚拟通道来传送以下信息:演示数据串行设备通信许可信息高度加密的数据,如键盘、鼠标活动RDP是T.Share核心协议的扩展。若干其他功......
  • Bypass 403 Forbidden 403页面绕过技巧
    介绍根据基础设施分析师所做的配置,有一些方法可以解决403禁止错误,通常是通过配置何时不允许您访问该目录或文件的某些资源。我创建了这个快速文档来演示一些技术,包括我已经使用它并设法通过403错误并访问数据库管理登录页面。一些技巧......
  • 蚂蚁SEO优化工具有哪些?
    在当今的数字化时代,网站已经成为企业展示自己的重要窗口。而要让网站在搜索引擎中获得更好的排名,SEO优化工具成为了必不可少的利器。那么,在繁多的SEO优化工具中,你究竟了解多少呢?本文将为你揭秘各种常用的SEO优化工具。如何联系蚂蚁seo?baidu搜索:如何联系蚂蚁SEO?baidu搜索:如何联系蚂......
  • 斜率优化入门 任务分配
    终于开始斜率优化了。。洛谷P2365任务安排题目描述nn个任务排成一个序列在一台机器上等待完成(顺序不得改变),这nn个任务被分成若干批,每批包含相邻的若干任务。从零时刻开始,这些任务被分批加工,第ii个任务单独完成所需的时间为titi​。在每批任务开始前,机器需要启动时间s......
  • 优化理论 目录
    学期内是更不动了,之后慢慢填。线性线性规划与多胞体的基本性质单纯形线性规划的对偶凸优化凸集与凸函数的基本性质椭球法线性规划与半正定规划松弛强对偶的两个充分条件-KKT/Slater'scondition.........
  • Python 潮流周刊#28:两种线程池、四种优化程序的方法
    你好,我是猫哥。这里每周分享优质的Python、AI及通用技术内容,大部分为英文。本周刊开源,欢迎投稿。另有电报频道作为副刊,补充发布更加丰富的资讯。......
  • 游戏是如何优化的?
    软件的编写要根据硬件的配置来设计如:(地平线)但是硬件是多样的开发软件,的时候没办法照顾所有游戏,做一个检测,他优化的时候要根据电脑的配置来做一个扩大把显卡的显存从8GB扩大到16GB,这个检测软件是和你的游戏一起安装下来的。......
  • 如何成为时间管理大师--时间管理的技巧
    工作注意事项和步骤提前与同事沟通以免漏掉更新点灵活使用便签工具记录新的内容将碰到的新问题记下来可以跟同事商量好一起去办公软件上去沟通互相交流共同吐槽有助于调整心情下班后好好地享受自己的时间认真工作快乐生活每天都在变化时间管理复盘每一个步骤的关键语句需要花费多长......