TLS协议基础

聊性能优化之前,得先把TLS协议本身摸透。我见过不少团队一上来就调参数,结果因为用了过时的版本或弱加密套件,安全都保不住,性能分析更是白折腾。这一章我们就从版本演进、加密套件、协议栈结构三个角度把地基打牢。

1.1 TLS版本演进史

说白了,TLS就是SSL的升级版。1995年网景搞出SSL 2.0,结果漏洞一堆。1996年SSL 3.0出来,算是勉强能用。后来IETF接手,1999年发布TLS 1.0(相当于SSL 3.1),2006年TLS 1.1,2008年TLS 1.2,2018年TLS 1.3。

关键转折点:TLS 1.3把握手从2-RTT砍到1-RTT(甚至0-RTT),性能飞跃。我在项目中遇到过客户要求兼容IE8,被迫用TLS 1.0,那性能惨不忍睹——每次建连多花几十毫秒。
版本发布年份核心变化安全状态性能特点
SSL 2.01995最早商用版本已废弃,严重漏洞极差
SSL 3.01996引入主密钥、改进握手已废弃(POODLE攻击)差
TLS 1.01999标准化,PRF改进已废弃(BEAST攻击)慢
TLS 1.12006隐式IV,CBC防御不推荐中等
TLS 1.22008AEAD支持,SHA-256广泛使用较好
TLS 1.320181-RTT握手,移除不安全算法当前推荐优
我曾经踩过坑:在老旧嵌入式设备上强制启用TLS 1.2,结果对方不支持,直接握手失败。后来我做了版本协商降级策略,才搞定。所以兼容性测试不能省,尤其跨系统场景。

1.2 核心加密套件

加密套件就是一组算法的组合,告诉双方怎么握手的。格式类似:密钥交换_身份认证_对称加密_消息认证。举个例子,ECDHE-RSA-AES128-GCM-SHA256:

  • ECDHE – 临时椭圆曲线Diffie-Hellman密钥交换(前向安全)
  • RSA – 用RSA证书做身份认证
  • AES128-GCM – 128位AES-GCM对称加密(AEAD)
  • SHA256 – 消息认证用SHA-256 HMAC

你想想看,TLS 1.3砍掉了多少套件?直接从TLS 1.2的37个缩到5个。为什么?因为那些带CBC、带RC4的算法又慢又不安全。我建议在生产环境只开放TLS 1.2以上的套件,且优先用ECDHE + AEAD。

套件名称密钥交换认证加密MAC适用场景
ECDHE-RSA-AES128-GCM-SHA256ECDHERSAAES-128-GCM内建AEAD通用推荐
ECDHE-ECDSA-AES256-GCM-SHA384ECDHEECDSAAES-256-GCM内建AEAD高安全需求
DHE-RSA-AES128-CBC-SHADHERSAAES-128-CBCSHA-1遗留兼容(不推荐)
TLS_CHACHA20_POLY1305_SHA256ECDHE任意CHACHA20-POLY1305内建AEAD移动端/无AES加速
实际项目里,我习惯用openssl ciphers -v 'HIGH:!aNULL:!eNULL:!LOW:!MEDIUM'先列一遍系统支持的套件,再按性能测试结果挑前三位。避免选到那些纯软件跑很慢的CBC套件。

1.3 TLS协议栈结构

TLS协议是分层的,跟TCP/IP很像。底层是记录层(Record Layer),上面跑握手协议、警报协议和应用数据协议。做性能优化时,我们最关心的就是记录层的开销和握手协议的RTT数。

下面这张图是我自己梳理的协议栈结构,画了好几次才满意。你注意看,握手协议里面又分成好几个子消息,TLS 1.3比1.2合并了一些步骤。

TLS协议栈结构(简化) 应用数据协议 (Application Data) 握手协议 (Handshake) 警报协议 (Alert) 记录层 (Record Layer) TCP/IP 传输层 TLS 1.2 握手子消息(简略) ClientHello → ServerHello → Certificate → ServerKeyExchange → ServerHelloDone → ClientKeyExchange → ChangeCipherSpec → Finished → [应用数据] (共2-RTT)
你看记录层下面直接扛着TCP/IP。在做性能分析时,我用tcpdump抓包,重点看记录层每个片段的大小和耗时。如果发现很多小片段(比如每个HTTP请求拆成好几个TLS记录),那就是Nagle算法干扰或MTU碎片问题,可以调MSS或启用TCP_NODELAY。

嗯,这里要注意:握手协议里最耗时的部分往往是证书验证和非对称密钥协商。我在一个高并发API网关项目里遇到过,每次握手光证书链校验就要吃掉2~3毫秒,后来启用OCSP Stapling和会话复用,才算把平均建连时间压到1毫秒以下。

千万不要在TLS 1.2里开那些没有前向安全的套件(比如纯RSA密钥交换)。一旦私钥泄露,之前所有通信记录都能被解密。我见过一个金融客户因为他们没禁用TLS_RSA_WITH_AES_128_CBC_SHA,被安全审计打了个高危。后来我帮他们改成了ECDHE套件,握手多了一次椭圆曲线运算,但安全性和性能都更均衡。

总结一下:版本越新性能越好,但得评估客户端兼容性;加密套件优先选AEAD+ECDHE;协议栈里记录层的MTU和握手子消息的RTT数是最值得优化的两个点。这些基础概念,后面几章会反复用到。