4. TLS版本演进与性能差异
TLS 1.3(RFC 8446)并不是 TLS 1.2 的小幅修订,而是一次针对“延迟”和“安全性”同时重构的协议。理解两者性能差异的关键,不在于记住版本号,而在于看清握手轮次、密钥交换机制、0-RTT 与会话恢复这四条主线如何共同决定一次连接要花几个 RTT、消耗多少 CPU、能否复用。
握手轮次:从 2-RTT 到 1-RTT 的实质变化
在 TLS 1.2 的完整握手中,客户端先发 ClientHello,服务端回 ServerHello、Certificate、ServerKeyExchange、ServerHelloDone;客户端再发 ClientKeyExchange、ChangeCipherSpec、Finished;服务端最后回 ChangeCipherSpec、Finished。整个流程需要 2 个 RTT 才能开始传输应用数据。若启用客户端证书,还会再多一轮。
TLS 1.3 把密钥交换的“参数协商”提前合并进 ClientHello 的 key_share 扩展中。客户端在第一个飞行包(flight)里就带上自己猜测的密钥交换公钥,服务端若接受,直接在 ServerHello 中返回自己的 key_share,随后即可发送加密的 Certificate、Finished。因此完整握手压缩到 1-RTT。对于已经访问过的站点,客户端还可以利用 PSK 直接发送 early data,实现 0-RTT。
需要强调的是,1-RTT 是“完整握手”的典型值,不是所有场景的保证。如果服务端不接受客户端的 key_share 组(例如客户端只发了 X25519,而服务端只支持 P-256),服务端会发 HelloRetryRequest,额外增加 1 个 RTT。因此实际部署中,客户端和服务端都应同时支持 X25519 与 P-256,避免重试。
密钥交换:从 RSA 到 (EC)DHE 的全面前向安全
TLS 1.2 允许使用静态 RSA 密钥交换:客户端用服务端证书公钥加密预主密钥(premaster secret)后发送。这种方式没有前向安全性(PFS),一旦服务端私钥泄露,历史流量可被解密。TLS 1.2 也支持 ECDHE,但属于可选。
TLS 1.3 强制使用 (EC)DHE 或 PSK,彻底移除了静态 RSA 和自定义 DH 组。密钥交换的默认推荐组是 X25519,其次 P-256。X25519 在同等安全强度下计算更快、密钥更短,对移动端和高并发服务端都更友好。此外,TLS 1.3 的密钥派生使用 HKDF,握手密钥与应用密钥分离,配合“密钥更新(KeyUpdate)”机制,可以在长连接中定期更换应用流量密钥。
0-RTT:收益与风险并存
0-RTT 允许客户端在第一个飞行包中携带 early data,服务端用 PSK 派生密钥直接解密,从而在 0 个额外 RTT 内开始处理请求。这对 API 首包、静态资源、幂等查询类请求收益明显。
但 0-RTT 数据不具备前向安全性,且可被重放。因此工程上必须限制:只对幂等请求(GET、HEAD)开启;服务端应记录 anti-replay 窗口(通常基于 ticket 生命周期);对非幂等操作(POST、支付、下单)禁用 0-RTT。Nginx 中可通过 ssl_early_data on; 开启,并在应用层用 Early-Data: 1 请求头识别并做重放防护。
会话恢复:Session ID / Session Ticket 与 PSK
TLS 1.2 的会话恢复依赖 Session ID 或 Session Ticket。Session ID 需要服务端保存会话状态,多机部署时需共享存储;Session Ticket 把状态加密后交给客户端保存,服务端无状态,但 ticket 密钥轮换和加密套件绑定较复杂。
TLS 1.3 统一用 PSK 做恢复。服务端在完整握手后下发 NewSessionTicket,客户端下次连接时在 ClientHello 的 pre_shared_key 扩展中携带该 ticket。恢复握手只需 1 个 RTT(若配合 0-RTT 则 0-RTT)。PSK 与密钥交换可以组合,形成“PSK + (EC)DHE”模式,既恢复会话又保持前向安全。
迁移策略:从双栈并行到逐步收敛
生产环境迁移 TLS 1.3 不建议“一刀切”。推荐路径是:先让服务端同时支持 TLS 1.2 与 TLS 1.3,客户端优先协商 1.3;观察握手成功率、0-RTT 接受率、重放拦截日志;再逐步对内部服务、静态资源、幂等 API 开启 0-RTT;最后根据客户端兼容性数据决定是否关闭 1.2。
以 Nginx 为例,一份可参考的配置如下:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_ecdh_curve X25519:P-256;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets on;
ssl_early_data on;
add_header Early-Data $ssl_early_data;
其中 ssl_prefer_server_ciphers off 让客户端优先选择,符合 TLS 1.3 的设计;ssl_ecdh_curve X25519:P-256 同时提供两个组,降低 HelloRetryRequest 概率;ssl_early_data on 开启 0-RTT,但必须配合应用层重放防护。
性能对比与判断依据
| 维度 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 完整握手轮次 | 2-RTT | 1-RTT(HelloRetryRequest 时 2-RTT) |
| 会话恢复轮次 | 1-RTT | 1-RTT(PSK)或 0-RTT(early data) |
| 密钥交换 | RSA(无 PFS)或 ECDHE(可选) | 强制 (EC)DHE 或 PSK,默认 X25519 |
| 前向安全 | 仅 ECDHE 套件具备 | 默认具备 |
| 0-RTT | 不支持 | 支持,但需防重放 |
| 典型首字节延迟 | 约 2×RTT + 计算 | 约 1×RTT + 计算(0-RTT 时约 0×RTT) |
判断迁移是否成功,可以观察三个指标:一是 TLS 1.3 协商占比是否持续上升;二是完整握手 P95 延迟是否下降约一个 RTT;三是 0-RTT 请求中是否出现异常重放告警。若 HelloRetryRequest 比例偏高,应检查客户端与服务端的 key_share 组是否对齐;若 0-RTT 被大量拒绝,应检查 ticket 生命周期与 anti-replay 窗口是否过短。