ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

第 2 篇:一次 TLS 握手到底发生了什么?

第 2 篇:一次 TLS 握手到底发生了什么? 第 2 篇一次 TLS 握手到底发生了什么TLS 1.2 / 1.3 对照标签#TLS#HTTPS#网络安全#密码学TLS 到底在做什么还记得第 1 篇里说的「TLS 是把多个密码学基元组合起来的协议框架」吗这一篇我们一起打开Wireshark的视角把抽象变成具体——看看一次 HTTPS 连接背后ClientHello 和 ServerHello 到底在聊什么。冷知识观察 TLS 最直接的方法是打开 Wireshark过滤tcp.port 443再访问任意 HTTPS 网站。Wireshark 自带 TLS 协议分析器每一条握手消息都能展开看字段。一次完整的 TLS 1.2 握手10 条消息、2 个 RTT理解 TLS 1.3 的改动先得看懂 TLS 1.2 在做什么。TLS 1.2 握手要做四件事交换能力互相告诉对方「我支持哪些协议版本、密码套件、扩展」验证身份服务器出示证书客户端验证协商密钥双方贡献材料得出共享主密钥验证握手用 Finished 消息确认整个握手过程没被篡改下图是 TLS 1.2 中「对服务器做身份验证」的完整流程Client Server | | |─────── 1. ClientHello ─────────────│ 客户端我支持的功能 |────── 2. ServerHello ──────────────│ 服务器我选了这些参数 |────── 3. Certificate ──────────────│ 服务器这是我的证书链 |────── 4. ServerKeyExchange ────────│ 服务器密钥交换参数ECDHE 时 |────── 5. ServerHelloDone ──────────│ 服务器我这边说完了 |─────── 6. ClientKeyExchange ───────│ 客户端我的密钥交换材料 |─────── 7. ChangeCipherSpec ───────│ 客户端切换到加密模式 |─────── 8. Finished ────────────────│ 客户端握手 MAC |─────── 9. ChangeCipherSpec ────────│ 服务器切换到加密模式 |────── 10. Finished ────────────────│ 服务器握手 MAC | | |═══════ Application Data ════════════│ 开始加密传输整个握手涉及2 个 RTT往返时延——这正是后面 TLS 1.3 要优化的关键。几条关键消息长什么样ClientHello客户端的第一句话Version: TLS 1.2 Random: 32 字节随机数含 4 字节客户端时间防弱 RNG Session ID: 空首次连接 Cipher Suites: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA ... Compression Methods: null Extensions: server_name, renegotiation_info, elliptic_curves, signature_algorithms, ...ServerHello服务器的回应只是上述每项的一个「选项」密码套件一旦选定握手后半程的格式就定了。冷知识ClientHello 里的 32 字节随机数中前 4 字节是「客户端时间」。这个字段是 1994 年 Netscape Navigator 因为 RNG 故障引入的「补丁」——通过时间戳增加随机性。但现代浏览器担心时间戳被用于浏览器指纹采集Chrome、Firefox 已经会给时间戳加随机扰动甚至完全随机化。ChangeCipherSpecTLS 1.2 的「设计瑕疵」注意上面第 7 条和第 9 条的ChangeCipherSpec——这条消息不属于握手协议它是另一种「子协议」独立实现的。结果就是它不参与握手完整性校验让 OpenSSL 在 2014 年 6 月为此出过事。TLS 1.3 的最大改动之一就是砍掉 ChangeCipherSpec——不再需要它。密钥交换RSA、DHE、ECDHE 该选谁握手最重要的环节就是「双方怎么安全地协商出一个共享密钥」。可用算法主要有 3 种算法前向保密性能当前建议RSA❌ 没有⚡ 极快❌已淘汰所有主流浏览器都禁了DHE_RSA✅ 有 慢⚠️ 仅在不支持 ECDHE 时作为备选ECDHE_RSA / ECDHE_ECDSA✅ 有⚡ 快✅首选主流配置RSA 密钥交换为什么被淘汰RSA 是密钥传输——客户端生成 48 字节预主密钥用服务器公钥加密后发过去服务器用私钥解密。问题在于服务器私钥通常几年不变攻击者只要未来某一天拿到服务器私钥就能解密所有历史会话——只要他当时记录了密文。真实教训斯诺登用的 Lavabit 邮件服务用的就是 RSA 密钥交换。FBI 拿传票获得服务器私钥后直接解密了斯诺登所有历史邮件。这是 2014 年敲响前向保密警钟的真实事件。ECDHE今天的事实标准DHE / ECDHE是密钥协商——双方各自贡献材料计算出共享密钥。即使服务器长期私钥泄露过去每个会话的临时密钥依然安全因为它们从未被持久化过。冷知识DHE 用整数取模运算慢ECDHE 用椭圆曲线点乘快很多且密钥短。所以今天几乎所有现代部署都用 ECDHE。常见的命名TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256用 RSA 证书做身份验证ECDHE 做密钥交换TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256用 ECDSA 证书做身份验证更高效密码套件怎么读TLS 1.2 套件的命名规则TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 │ │ │ │ │ │ │ │ │ │ │ │ │ └─ PRFTLS 1.2或 MAC 算法 │ │ │ │ │ └─────── 加密模式GCM AEAD │ │ │ │ └──────────── 密钥长度128 位 │ │ │ └────────────────── 对称算法AES │ │ └────────────────────────── 身份验证算法RSA │ └────────────────────────────────── 密钥交换算法ECDHE └──────────────────────────────────────── 前缀读出三件事就够了密钥交换 身份验证 对称加密。括号后的 PRF/MAC 在 AEAD 套件中几乎可以忽略——因为 AEAD 已经把加密和完整性打包了。TLS 1.2 的「今天还行的」套件套件今天的处境TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256✅首选TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384✅ 仍然可用TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA❌3DES 已完全弃用TLS_RSA_WITH_AES_128_CBC_SHA❌RSA 密钥交换已淘汰TLS_ECDHE_ECDSA_WITH_AES_128_CCM⚠️ 仅在受限环境使用TLS 1.3 的密码套件从「复杂长串」到「清爽短名」TLS 1.3 把密码套件数量从300 个砍到只剩 5 个且不再把密钥交换方法写进套件名字因为 TLS 1.3 强制 ECDHETLS_AES_128_GCM_SHA256 TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_CCM_SHA256 TLS_AES_128_CCM_8_SHA256密钥交换和身份验证全部通过扩展协商——更干净但也意味着「旧式的把 ECDHE 写进套件名」的做法在 1.3 里不存在了。TLS 扩展协议演进的主战场TLS 的演进几乎都通过扩展完成不动协议本身。这里挑 4 个最重要的扩展作用现状SNIserver_name让客户端告诉服务器「我要访问哪个域名」实现 HTTPS 虚拟主机✅ 必备但 SNI 仍是明文泄露你访问的网站ALPN应用层协议协商在 TLS 内部协商 HTTP/2、HTTP/3✅ 取代了 NPN已被淘汰OCSP stapling服务器把证书吊销状态「盖章」带在握手里避免客户端单独查 OCSP✅ 主流服务器默认启用signature_algorithms客户端声明支持的签名/哈希算法对✅ 必须让 SHA-1 签名被淘汰冷知识SNI 明文泄露访问目标的问题ECHEncrypted Client Hello已经标准化——Cloudflare 已支持Firefox 已默认启用。Chrome 也在跟进。TLS 1.3把 TLS 1.2 推倒重来2018RFC 8446TLS 1.3 是过去十几年 TLS 协议最大的改动主要做了 4 件大事。① 1-RTT 握手甚至 0-RTTTLS 1.2 需要2-RTT才能开始传应用数据TLS 1.3 把客户端能力提前到第一个消息服务器响应里同时携带自己的能力和证书。结果1-RTT 即可开始传数据。更进一步0-RTT模式允许客户端在第一次握手时就发送加密的应用数据适合重连场景——但要注意重放风险0-RTT 数据可能被攻击者捕获并重发所以敏感操作如下单、付款绝对不能用 0-RTT。② 强制前向保密TLS 1.3直接删除了所有静态 RSA / 静态 DH 密钥交换只剩 ECDHE / DHE。这意味着 TLS 1.3 配置错误的空间被极大压缩——你不可能再「不小心」配出一个无前向保密的服务器。③ 简化密码套件如上所述300 个套件 → 5 个套件全部 AEAD密钥交换从套件名里剥离。④ 删除/重做不安全特性ChangeCipherSpec 被删除压缩被完全删除防 CRIME 类攻击静态 RSA、3DES、RC4 全部被删重协商机制被重做TLS 1.3 用key_update替代MAC-then-encrypt 改为 encrypt-then-MAC / AEAD冷知识TLS 1.3 把 Finished 消息的 verify_data 从 12 字节固定为 32 字节SHA-256部分原因是研究显示 12 字节在某些情况下可能不足以抵抗生日攻击。TLS 1.3 的流程4 条消息、1-RTTClient Server | | |─────── 1. ClientHello Key Share ──│ 客户端能力 临时 ECDHE 公钥 |────── 2. ServerHello Key Share ───│ 服务器选了这些 临时 ECDHE 公钥 |─────── Encrypted Extensions ────────│ 服务器扩展现在是加密的 |─────── Certificate ─────────────────│ 服务器证书链 |─────── CertificateVerify ───────────│ 服务器用私钥对握手做签名 |─────── Finished ────────────────────│ 服务器握手完整性证明 |─────── Finished ───────────────────│ 客户端握手完整性证明 | | |═══════ Application Data ════════════│ 开始加密传输注意差异去掉了 ServerKeyExchange / ClientKeyExchange / ChangeCipherSpecServerHello 之后所有消息都是加密的——攻击者看不到证书、看不到扩展握手从 10 条消息 → 6 条消息从 2-RTT → 1-RTT给开发者的三条建议① 服务器只开 TLS 1.2 TLS 1.3不要开 TLS 1.0/1.1已被所有主流浏览器弃用不要开 SSLv3POODLE 攻击。Nginx 示例ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; # TLS 1.3 套件由浏览器和 OpenSSL 自动协商无需手动指定② 部署 ECH 或至少启用 OCSP staplingECHEncrypted Client Hello解决 SNI 明文泄露。Cloudflare 已支持Firefox 已启用。OCSP stapling服务器把证书吊销状态「随身带」避免客户端单独请求 OCSP性能 隐私双赢。③ 学会用openssl s_client看握手# 查看服务器实际协商的协议版本和密码套件openssl s_client-connectexample.com:443-tls1_3# 只看握手关键信息openssl s_client-connectexample.com:4432/dev/null\|grep-EProtocol|Cipher|subject|issuer 延伸阅读RFC 5246 — TLS 1.2RFC 8446 — TLS 1.3 — 现代化必读RFC 8446 中文翻译 — 中文社区翻译The Illustrated TLS 1.3 Connection — 图解版每条消息都有插图Cloudflare 博客 — TLS 1.3 / ECH / 后量子密码学最新进展Mozilla SSL Configuration Generator — 一键生成各服务器的安全配置
返回列表