TLS 1.3 握手过程的一点笔记
2026-09-30
排障的时候经常要看握手,索性把过程记一遍,下次不用再翻文档。
TLS 1.3 把完整的握手压缩到了一次往返。客户端发出 ClientHello,里面带上支持的密钥交换组、签名算法、SNI 和一串 key_share(通常是 x25519,有时还有 secp256r1)。服务端如果认这个组,就直接用自己的临时私钥算出共享密钥,在 ServerHello 里给出自己的 key_share,之后的所有握手消息都已经加密了。
所以抓包时能看到的是:ClientHello 明文,ServerHello 的后半段开始就只能看到 encrypted extensions 了。证书、CertificateVerify、Finished 全在加密的 flight 里。
看协商结果的办法
openssl s_client -connect example.com:443 \
-servername example.com -tls1_3 </dev/null \
| grep -E "Protocol|Cipher|Server Temp Key|Verify return code"
几个常见字段的解释:
Server Temp Key: X25519, 253 bits—— 说明用的是 x25519 临时密钥交换;Cipher: TLS_AES_256_GCM_SHA384—— 1.3 的 cipher suite 只描述 AEAD 和 HKDF,不再描述密钥交换;Verify return code: 0 (ok)—— 证书链校验通过,注意这只校验链,不校验域名。
要强制某个组
可以用 -groups 指定,验证服务端是否真的支持:
openssl s_client -connect example.com:443 -tls1_3 -groups X25519
如果服务端不支持这个组,会直接握手失败,返回 no shared cipher 或者 handshake failure。这个办法在挑选对端、确认配置有没有生效时挺有用。
顺带一提,1.3 里会话恢复用的是 PSK 票据,和服务端会话缓存不是一回事。看到 Reused 字样不代表配置就一定对。
OCSP Stapling 还值得开吗
Let's Encrypt 在 2025 年已经停止签发带 OCSP 地址的证书了,所以新证书的 stapling 基本是空转。老证书(2025 年之前签发的)在有效期内还能用一阵,之后这块配置就可以从 nginx 里删掉了。