文章目录一、为什么必须单独学 TLS 1.3二、TLS 记录层与握手消息总览2.1 四层封装复习2.2 TLS 1.3 完整握手「一图流」三、动画级分帧ClientHello帧 ①3.1 客户端发出什么3.2 关键扩展详解3.3 「动画」客户端在想什么四、动画级分帧ServerHello帧 ②4.1 服务器选择参数4.2 密钥派生概念动画4.3 「动画」服务器侧五、动画级分帧加密握手段帧 ③④5.1 EncryptedExtensions5.2 Certificate CertificateVerify5.3 Finished5.4 握手完成状态机六、TLS 1.3 套件与算法安全视角6.1 仅 AEAD 套件6.2 密钥交换组七、0-RTT 与会话恢复动画补充7.1 1-RTT 恢复PSK7.2 0-RTT Early Data7.3 Wireshark 识别八、实验环境8.1 拓扑8.2 nginx 启用 TLS 1.38.3 确认 OpenSSL 与 curl 支持九、Wireshark 抓包与解密配置9.1 抓包9.2 SSLKEYLOGFILE推荐9.3 强制完整握手避免 PSK 干扰观察十、Wireshark 逐包验证清单10.1 第一包ClientHello10.2 第二包ServerHello10.3 加密握手段10.4 应用数据10.5 对照实验记录表实验报告模板十一、TLS 1.2 vs 1.3同屏对比实验11.1 强制 TLS 1.2 抓一包11.2 动画对比十二、降级攻击与 Middlebox 兼容12.1 为何 ClientHello 写 TLS 1.212.2 降级攻击防护12.3 测试服务器最低版本十三、常见踩坑十四、安全加固建议运维向十五、与攻击链的关联十六、完整实验步骤90 分钟十七、本篇小结附录 AWireshark 过滤器速查附录 Bopenssl 调试命令附录 C握手消息类型编号附录 D与专栏前篇关联定位网络基础与协议安全篇 · 把 TLS 1.3 握手机制「逐帧看懂」声明抓包与密钥日志实验仅限自有靶场或授权环境勿对未授权流量解密分析。一、为什么必须单独学 TLS 1.3上一篇讲了 HTTPS 抓包与解密但TLS 1.2 与 1.3 握手差异巨大对比项TLS 1.2TLS 1.3完整握手 RTT2-RTT常见1-RTT恢复会话Session ID / TicketPSK 0-RTT密钥交换RSA、DHE、ECDHE 混用仅 ECDHE/DHE前向保密证书发送时机ServerHello 后明文ServerHello 后加密废弃算法仍可能见到RC4、3DES、EXPORT、RSA 密钥传输等移除中间人可见更多握手明文仅 ClientHello / ServerHello 主体可见不懂 1.3Wireshark 里会出现「Server Hello 之后全 Application Data」的断层误以为是抓包坏了。本文用动画级分帧图 逐字段对照在靶场里一次验证通过。二、TLS 记录层与握手消息总览2.1 四层封装复习┌──────────────────────────────────────┐ │ HTTP / HTTP/2 应用数据 │ ├──────────────────────────────────────┤ │ TLS 记录层Content Type 密文 │ ← 本文重点 ├──────────────────────────────────────┤ │ TCP │ ├──────────────────────────────────────┤ │ IP │ └──────────────────────────────────────┘Content Type记录层类型值含义TLS 1.3 说明22HandshakeClientHello、ServerHello 等23Application Data加密后的 HTTP20ChangeCipherSpec1.3 中通常不出现兼容旧栈时可能有21Alert警告/关闭2.2 TLS 1.3 完整握手「一图流」时间 → 客户端 服务器 │ │ │════════ ClientHello ══════════════════════════════►│ ① 明文 │ 版本、套件、key_share、SNI、supported_versions │ │ │ │◄════════ ServerHello ═════════════════════════════│ ② 明文 │◄──────── {EncryptedExtensions} ────────────────────│ ③ 起加密 │◄──────── {Certificate} ──────────────────────────│ │◄──────── {CertificateVerify} ────────────────────│ │◄──────── {Finished} ─────────────────────────────│ │ │ │──────── {Finished} ───────────────────────────────►│ ④ 客户端确认 │ │ │════════ Application Data (HTTP) ═════════════════►│ ⑤ 应用数据 │◄════════ Application Data ═══════════════════════│大括号{ }表示使用握手流量密钥Handshake Traffic Secret加密Wireshark 配好密钥后可展开。三、动画级分帧ClientHello帧 ①3.1 客户端发出什么[帧 ①] ClientHello ┌─────────────────────────────────────────┐ │ Handshake Type: Client Hello (1) │ │ Legacy Version: 0x0303 (TLS 1.2 伪装) │ ← 兼容中间盒 │ Random: 32 字节客户端随机数 │ │ Session ID: 空或 PSK 会话标识 │ │ Cipher Suites: TLS_AES_128_GCM... 等 │ │ Compression: null (0) │ │ Extensions: │ │ ├─ server_name (SNI) │ │ ├─ supported_versions (真正声明 1.3) │ │ ├─ supported_groups (x25519 等) │ │ ├─ key_share (客户端 ECDHE 公钥) │ ← 1.3 核心 │ ├─ signature_algorithms │ │ ├─ psk_key_exchange_modes (可选) │ │ └─ ... │ └─────────────────────────────────────────┘3.2 关键扩展详解扩展作用安全意义supported_versions声明支持 TLS 1.3真正版本协商处Legacy Version 常为 0x0303key_share客户端临时 ECDHE 公钥1-RTT 密钥材料前向保密server_name (SNI)目标域名仍明文虚拟主机必备signature_algorithms签名哈希算法列表验证书链用psk_key_exchange_modesPSK 模式为 0-RTT / 会话恢复铺路3.3 「动画」客户端在想什么T0ms 用户输入 https://lab.local T1ms DNS 解析 → TCP SYN → SYN-ACK → ACK T5ms 构造 ClientHello · 我支持 TLS 1.3 · 我选 x25519公钥是 [ClientPubKey] · 我要去的服务器名叫 lab.local T6ms 发出 ClientHello ───────────────►四、动画级分帧ServerHello帧 ②4.1 服务器选择参数[帧 ②] ServerHello ┌─────────────────────────────────────────┐ │ Handshake Type: Server Hello (2) │ │ Legacy Version: 0x0303 │ │ Random: 32 字节末 8 字节有特殊含义* │ │ Session ID: ... │ │ Cipher Suite: TLS_AES_256_GCM_SHA384 │ ← 选定套件 │ Extensions: │ │ ├─ supported_versions: TLS 1.3 (0x0304)│ │ └─ key_share: x25519 [ServerPubKey] │ ← 服务端临时公钥 └─────────────────────────────────────────┘ * 若协商 TLS 1.3Random 最后 8 字节固定为特殊模式便于区分降级攻击 Wireshark 中可见 TLS 1.3 标注4.2 密钥派生概念动画ClientHello.key_share ServerHello.key_share ↓ ECDH 运算 Shared Secret共享秘密 ↓ HKDF 扩展 Handshake Traffic Secret握手期密钥 ↓ 加密后续握手消息 {Certificate} {Finished} ... ↓ 双方 Finished 完成 Application Traffic Secret应用期密钥 ↓ HTTP 密文双向流动前向保密PFS临时 ECDHE 私钥会话结束即丢弃历史抓包无法用长期私钥解密——这也是上一篇「拿 nginx 私钥解 ECDHE 流量失败」的原因。4.3 「动画」服务器侧T20ms 收到 ClientHello T22ms 选择 TLS_AES_256_GCM_SHA384 x25519 T23ms 生成 ServerPubKey计算 Shared Secret T24ms 派生 Handshake Traffic Secret T25ms 发出 ServerHello ──────────────► T26ms 同 TCP 段或紧随其后发出加密的 EncryptedExtensions Certificate CertificateVerify Finished1-RTT 含义客户端发完 ClientHello等一轮服务器响应后双方已可推导出应用密钥客户端还需发 Finished但应用数据可紧跟。五、动画级分帧加密握手段帧 ③④5.1 EncryptedExtensions[帧 ③a] {EncryptedExtensions} ┌─────────────────────────────────────────┐ │ 解密后常见扩展 │ │ ├─ application_layer_protocol_negotiation (ALPN: h2 / http/1.1) │ ├─ max_fragment_length │ └─ server_name 相关确认较少 │ └─────────────────────────────────────────┘ALPN决定走 HTTP/2 还是 HTTP/1.1解密后 Wireshark 会显示h2或http。5.2 Certificate CertificateVerify[帧 ③b] {Certificate} 服务器证书链叶子 中间 CA [帧 ③c] {CertificateVerify} 服务器用私钥对「至今所有握手 transcript」签名 证明持有证书对应私钥的人参与了本次握手5.3 Finished[帧 ③d] {Finished} 服务端 对完整握手 transcript 的 MAC证明握手未被篡改 [帧 ④] {Finished} 客户端──► 客户端同样确认 transcript5.4 握手完成状态机ClientHello │ ▼ ServerHello ──► 双方有 Handshake Secret │ ▼ 加密段到达 解密成功 │ ▼ Client Finished ──► Application Secret 就绪 │ ▼ Application DataHTTP六、TLS 1.3 套件与算法安全视角6.1 仅 AEAD 套件TLS 1.3 标准化套件示例套件名加密哈希TLS_AES_128_GCM_SHA256AES-128-GCMSHA256TLS_AES_256_GCM_SHA384AES-256-GCMSHA384TLS_CHACHA20_POLY1305_SHA256ChaCha20-Poly1305SHA256不再有TLS_RSA_WITH_AES_...这类 RSA 密钥传输套件。6.2 密钥交换组组说明x25519最常用速度快secp256r1 (P-256)NIST 曲线secp384r1更高强度蓝队检查禁用弱曲线、强制 TLS 1.3-only视业务兼容性。七、0-RTT 与会话恢复动画补充7.1 1-RTT 恢复PSK老用户第二次访问客户端 服务器 │ │ │ ClientHello │ │ pre_shared_key (PSK identity binder) │ │ key_share (可选用于 PFS 混合模式) │ ├───────────────────────────────────────────────────►│ │◄ ServerHello {EncryptedExtensions} │ │◄ {Finished} │ │ {Finished} ───────────────────────────────────────►│ │ Application Data ═════════════════════════════════►│Binder证明 ClientHello 未被篡改防 PSK 重放。7.2 0-RTT Early Data客户端 服务器 │ │ │ ClientHello Early Data (HTTP GET 已加密发出) │ ├───────────────────────────────────────────────────►│ │◄ ServerHello ... │优点风险省 1 RTT首包更快Early Data无前向保密适合 CDN、重复 GET重放攻击攻击者可重放 0-RTT 请求防御服务器对 0-RTT 请求只放行幂等操作安全策略严格时直接禁用 0-RTT。7.3 Wireshark 识别tls.handshake.extensions.early_data tls.handshake.extensions.pre_shared_key八、实验环境8.1 拓扑受害机 / Web 192.168.56.30 nginx TLS 1.3 分析机 Kali 或本机 Wireshark 4.x 测试客户端 同网段浏览器或 curl8.2 nginx 启用 TLS 1.3# Ubuntu 22.04 / 较新 OpenSSLsudoaptinstall-ynginx opensslsudotee/etc/nginx/snippets/tls13.confEOF ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:TLS_AES_256_GCM_SHA384; ssl_prefer_server_ciphers off; EOF# 在 443 server 块 include snippets/tls13.confsudonginx-tsudosystemctl reload nginx# 验证echo|openssl s_client-connect192.168.56.30:443-tls1_32/dev/null|grepProtocol# 应见 Protocol : TLSv1.38.3 确认 OpenSSL 与 curl 支持openssl version# 1.1.1 支持 TLS 1.3curl--tlsv1.3-vkhttps://192.168.56.30/九、Wireshark 抓包与解密配置9.1 抓包# 在 Web 服务器或 Kali 镜像口sudowireshark-ieth1-fhost 192.168.56.30 and tcp port 443另开终端触发握手每次测试新开隐私窗口避免会话恢复干扰curl--tlsv1.3-vkhttps://192.168.56.30/-o/dev/null9.2 SSLKEYLOGFILE推荐exportSSLKEYLOGFILE/tmp/tls13.keys.log chromium https://192.168.56.30/# 或 Chrome# Wireshark → Edit → Preferences → Protocols → TLS# (Pre)-Master-Secret log filename → /tmp/tls13.keys.log重新加载抓包文件后加密握手段与 Application Data 应可解密。9.3 强制完整握手避免 PSK 干扰观察· 浏览器隐私模式 · curl 每次新连接curl --tlsv1.3 --no-sessionid · 服务器侧重载 nginx 清空 ticket靶场十、Wireshark 逐包验证清单10.1 第一包ClientHello过滤器tls.handshake.type 1核对表字段期望Handshake TypeClient Hello (1)Version (Legacy)0x0303Extension: supported_versions包含 TLS 1.3 (0x0304)Extension: key_share含 x25519 与公钥长度 32 字节Extension: server_name你的域名或 IPCipher Suites含 TLS_AES_128_GCM_SHA256 等展开路径示例Transport Layer Security └─ TLSv1.3 Record Layer: Handshake Protocol: Client Hello └─ Extension: supported_versions (TLS 1.3) └─ Extension: key_share (x25519)10.2 第二包ServerHellotls.handshake.type 2字段期望supported_versionsTLS 1.3选中Cipher SuiteTLS_AES_256_GCM_SHA384 等key_share服务端 x25519 公钥10.3 加密握手段解密成功后同一 TCP 流中应看到Handshake Protocol: Encrypted Extensions Handshake Protocol: Certificate Handshake Protocol: Certificate Verify Handshake Protocol: Finished过滤器解密后tls.handshake.type 8 # Encrypted Extensions tls.handshake.type 11 # Certificate tls.handshake.type 15 # Certificate Verify tls.handshake.type 20 # Finished10.4 应用数据http || http2或tls.record.content_type 23Follow → HTTP/2 Stream 或 HTTP Stream看到GET /即全链路打通。10.5 对照实验记录表实验报告模板序号消息明文/加密关键字段截图编号1ClientHello明文supported_versions, key_share, SNIfig-012ServerHello明文选定套件、Server key_sharefig-023EncryptedExtensions加密ALPN h2/http1.1fig-034Certificate加密颁发者、SANfig-045Finished ×2加密握手完成fig-056Application Data加密→解密GET 请求fig-06十一、TLS 1.2 vs 1.3同屏对比实验11.1 强制 TLS 1.2 抓一包curl--tlsv1.2-vkhttps://192.168.56.30/-o/dev/null现象TLS 1.2TLS 1.3ServerHello 后常有Certificate 明文Certificate在加密块内密钥交换ServerKeyExchange / ClientKeyExchange 可能单独出现合并进 key_share报文数量通常更多更少、更紧凑ChangeCipherSpec常见通常无过滤器对比tls.handshake.type 11 frame.number 501.2 往往在早期帧即可见 Certificate1.3 需解密后才见。11.2 动画对比TLS 1.2简化: C: ClientHello ──────► S: ServerHello ───────► S: Certificate ───────► 明文 S: ServerHelloDone ───► C: ClientKeyExchange ─► C: ChangeCipherSpec ──► C: Finished ──────────► S: ChangeCipherSpec ──► S: Finished ──────────► ══ Application Data ══ TLS 1.3: C: ClientHello ──────► S: ServerHello {CertFinished...} ──► C: {Finished} ───────► ══ Application Data ══十二、降级攻击与 Middlebox 兼容12.1 为何 ClientHello 写 TLS 1.2部分老旧防火墙见到「非 0x0303」就丢包。客户端在Legacy Record Layer写 0x0303在supported_versions扩展里声明 1.3。12.2 降级攻击防护TLS 1.3 在 ServerHello Random 嵌入特殊标记Finished 覆盖完整 transcript。蓝队禁用服务器 TLS 1.0/1.1/1.2可减攻击面需评估业务。12.3 测试服务器最低版本# 应失败若仅允许 1.2openssl s_client-connect192.168.56.30:443-tls1# 应成功openssl s_client-connect192.168.56.30:443-tls1_3十三、常见踩坑问题原因解决看不到 TLS 1.3OpenSSL/nginx 过旧升级检查ssl_protocolsServerHello 后「断层」1.3 握手加密配置 SSLKEYLOGFILE一直是 Session Ticket 恢复浏览器缓存 PSK隐私窗口 /--no-sessionidWireshark 显示 TLS 1.2仅看 Legacy Version看supported_versions扩展解密后无 Certificate解密失败或走 1.2检查 key log 路径、重抓curl 无 1.3curl/openssl 旧curl -V检查ALPN 协商 h2 但看不懂HTTP/2 二进制分帧用 Follow HTTP/2 Stream十四、安全加固建议运维向□ ssl_protocols 至少 TLSv1.2 TLSv1.3优先淘汰 1.2 □ 证书 ECDSA P-256 或 RSA 2048自动续期 □ 启用 OCSP Stapling □ 评估 0-RTT对外 API 建议 off □ 配置 HSTS见 HTTPS 篇 □ 定期 sslscan / testssl.sh 扫描弱套件testssl.sh 快测gitclone https://github.com/drwetter/testssl.sh.git ./testssl.sh--protocols192.168.56.30:443十五、与攻击链的关联TLS 1.3 普及 → 纯「拿服务器 RSA 私钥解流量」失效 → MITM 更依赖「用户信任恶意 CA」或 SSL 剥离 → 0-RTT 重放成为新审计点 → 元数据SNI、JA3仍是监控入口下一篇SSL 剥离 将解释即使有 HTTPS为何仍可能「翻车」。十六、完整实验步骤90 分钟□ 1. nginx 开启 TLS 1.3openssl s_client 验证 □ 2. 配置 SSLKEYLOGFILE Wireshark TLS 密钥路径 □ 3. 隐私窗口访问 https://192.168.56.30保存 full.pcapng □ 4. 定位 ClientHello截图 supported_versions key_share □ 5. 定位 ServerHello确认选中 TLS 1.3 与套件 □ 6. 解密后展开 Certificate、ALPN □ 7. Follow HTTP/2 或 HTTP确认应用层 □ 8. 再抓一包 curl --tlsv1.2对比 Certificate 是否早期明文 □ 9. 可选抓 0-RTT同站第二次访问查 early_data 扩展 □ 10. 填写「对照实验记录表」写 200 字握手总结十七、本篇小结┌─────────────────────────────────────────────────────────────┐ │ TLS 1.3 核心记忆 │ ├─────────────────────────────────────────────────────────────┤ │ 1-RTTClientHello → ServerHello 加密块 → Client Finished │ │ 版本在 supported_versionskey_share 完成 ECDHE │ │ Certificate 在握手加密段内无密钥则 Wireshark「断层」 │ │ SSLKEYLOGFILE 是本地学习解密的最佳合法手段 │ │ 0-RTT 快但有重放风险PFS 使历史密文难用长期私钥破解 │ └─────────────────────────────────────────────────────────────┘下一篇预告《一次真实的 SSL 剥离攻击为什么 HTTPS 也会翻车》——HSTS、sslstrip、透明代理的组合拳。附录 AWireshark 过滤器速查tls tls.handshake.type 1 tls.handshake.type 2 tls.handshake.extensions_server_name tls.handshake.extensions.supported_versions tls.handshake.extensions_key_share tls.handshake.type 8 ssl.handshake.type 11 http2附录 Bopenssl 调试命令# TLS 1.3 握手详情openssl s_client-connect192.168.56.30:443-tls1_3-msg# 查看套件openssl ciphers-v|grepTLS_AES# 会话复用测试openssl s_client-connect192.168.56.30:443-tls1_3-reconnect附录 C握手消息类型编号Type名称TLS 1.3 常见1ClientHello✓2ServerHello✓8EncryptedExtensions✓11Certificate✓15CertificateVerify✓20Finished✓附录 D与专栏前篇关联前篇关联HTTP/HTTPS解密 Application Data 的前提Wireshark显示过滤器 TLS 密钥配置ARP MITM握手可见内容仍加密剥离攻击在应用层