每次 HTTPS 连接都做完整握手太浪费:TLS 的会话恢复让客户端带着上次的“票”回来。这篇测它省了什么(1.2 里是一个往返,1.3 里是证书和计算,不是往返)、ClientHello 里多了什么、ticket 能用几次,以及传说中的 0-RTT 在真实服务器上到底开不开。
完整握手:耗时(ms)[807, 155, 802, 166, 175],中位 175;服务器→客户端 6563 字节,客户端→服务器 1689 字节(中位,包含收发各一次 HTTP 请求和响应) 恢复握手:耗时(ms)[169, 1503, 169, 154, 600],中位 169;session_reused = [True, True, True, True, True];服务器→客户端 2800 字节,客户端→服务器 1960 字节(中位) session 对象:SSLSession,has_ticket = True,ticket 生存期提示 7200 秒(2.0 小时)
省证书和计算,不省往返:耗时 175 对 169 ms,但服务器→客户端字节降到不到一半。
完整握手的 ClientHello 1526 字节,扩展:['renegotiation_info', 'server_name', 'ec_point_formats', 'supported_groups', 'session_ticket', 'ALPN', 'encrypt_then_mac', 'extended_master_secret', 'signature_algorithms', 'supported_versions', 'psk_key_exchange_modes', 'key_share'] 恢复握手的 ClientHello 1797 字节,扩展:['renegotiation_info', 'server_name', 'ec_point_formats', 'supported_groups', 'session_ticket', 'ALPN', 'encrypt_then_mac', 'extended_master_secret', 'signature_algorithms', 'supported_versions', 'psk_key_exchange_modes', 'key_share', 'pre_shared_key'] 恢复的 ClientHello 多了 pre_shared_key 扩展(267 字节:里面是 ticket 本身 + 一个 binder,用来证明客户端知道密钥),并且它必须是最后一个扩展 完整握手的 ServerHello 扩展:['key_share', 'supported_versions'];恢复握手的 ServerHello 扩展:['pre_shared_key', 'key_share', 'supported_versions'](pre_shared_key 表示服务器接受了恢复) 服务器在 ServerHello 之后发的加密记录:完整握手 [3859, 477, 940, 22, 19],恢复握手 [90, 477, 940, 22, 19]——恢复时不再发证书(完整握手的那个 3000+ 字节记录),只剩 Finished 之类的小记录
恢复的 ClientHello 多一个 267 字节的 pre_shared_key,ServerHello 多 pre_shared_key,不再发证书。
TLS 1.2 完整握手:[327, 891, 322, 306, 319],中位 322 ms;恢复握手:[157, 155, 154, 163, 153],中位 155 ms;session_reused = [True, True, True, True, True] 对比 TLS 1.3:完整 175 ms,恢复 169 ms——TLS 1.3 的完整握手本来就只要 1 个往返,恢复省的是证书和计算,不省往返
完整 2 个往返,恢复 1 个:322 → 155 ms。
连续 4 次用同一个 ticket:(是否恢复, 握手 ms) = [(True, 166), (True, 190), (True, 162), (True, 162)] TLS 1.3 规范建议 ticket 只用一次(防重放和跨连接关联),服务器可以拒绝重复使用;这里看到服务器是否接受重复使用
同一个 ticket 连用 4 次都成功,但会让不同连接可被关联。
第一次连接(openssl):Protocol : TLSv1.3; TLS session ticket lifetime hint: 64800 (seconds); Max Early Data: 0; Protocol : TLSv1.3; TLS session ticket lifetime hint: 64800 (seconds); Max Early Data: 0 第二次(带 ticket 并要求发 early data):Reused, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384; Early data was not sent 服务器收到了 1 个 NewSessionTicket(openssl 在输出里打印了每个 ticket 的信息);Max Early Data 为 0 表示服务器没有允许 0-RTT——这个站点关闭了 0-RTT
example.com 不允许早期数据,恢复成功但 early data 没发出。