1. TLS 协议基础:从 SSL 到 TLS 的演进之路
聊 TLS 终止技术之前,咱们得先把地基打牢。TLS 协议本身,说白了就是给网络通信加了一把「加密锁」。我在做安全架构评审时,发现很多团队把 TLS 和 SSL 混着叫,其实这里头有段历史。
1.1 TLS 发展历史:一场被迫的升级
TLS 的前身是 SSL,全称 Secure Sockets Layer。网景公司在 1994 年搞出了 SSL 1.0,但压根没公开发布——因为漏洞太多,内部就毙掉了。真正面世的是 1995 年的 SSL 2.0,不过那玩意儿现在看简直是筛子。
我记得 2014 年有个客户还在用 SSL 3.0,我劝他升级,他说「跑得好好的换它干嘛」。结果没过几个月,POODLE 攻击爆出来,SSL 3.0 彻底凉了。嗯,这就是不升级的代价。
| 版本 | 发布年份 | 状态 | 关键问题 |
|---|---|---|---|
| SSL 1.0 | 1994 | 未公开发布 | 内部发现严重安全缺陷 |
| SSL 2.0 | 1995 | 已废弃(2011) | 无证书链验证、MAC 弱 |
| SSL 3.0 | 1996 | 已废弃(2015) | POODLE 攻击、RC4 弱 |
| TLS 1.0 | 1999 | 已废弃(2021) | BEAST 攻击、CBC 模式问题 |
| TLS 1.1 | 2006 | 已废弃(2021) | 改进 CBC、增加 IV |
| TLS 1.2 | 2008 | 广泛使用 | AEAD 支持、GCM 引入 |
| TLS 1.3 | 2018 | 推荐使用 | 1-RTT、前向安全、移除不安全算法 |
核心结论:现在生产环境最低也得 TLS 1.2,能用 TLS 1.3 就别犹豫。SSL 全系列已经进坟墓了,别挖出来用。
1.2 TLS 与 SSL 的关系:父子还是兄弟?
很多人以为 TLS 是 SSL 的改名版,其实不完全是。1999 年 IETF 接手了 SSL 标准化工作,觉得「SSL」这名字被网景注册了,干脆改叫 Transport Layer Security。但底层设计基本继承自 SSL 3.0。
你想想看,TLS 1.0 和 SSL 3.0 的差异其实很小,小到很多实现里 TLS 1.0 就是 SSL 3.1。但到了 TLS 1.3,改动就大了——握手从 2-RTT 砍到 1-RTT,还砍掉了一堆不安全算法。
我的建议:写代码或配服务器时,别在配置里写 SSL 了。Nginx 里配 ssl_protocols 只是历史遗留命名,实际走的是 TLS。统一叫 TLS,显得专业。
1.3 TLS 握手协议概述:一次加密的「对暗号」
TLS 握手,说白了就是客户端和服务器互相确认身份、商量加密方式的过程。我在调一个跨国电商的 HTTPS 性能时,发现握手占了连接建立时间的 70%。优化握手,就是优化用户体验。
咱们先看 TLS 1.2 的完整握手流程,这是最经典的版本:
- ClientHello:客户端发个招呼,带上支持的 TLS 版本、密码套件列表、随机数。
- ServerHello:服务器从列表里挑一个密码套件,发回自己的随机数和证书。
- Certificate:服务器把证书链发给客户端,客户端验证合法性。
- ServerKeyExchange:如果是 DHE/ECDHE 密钥交换,服务器发临时公钥。
- ServerHelloDone:服务器说「我发完了」。
- ClientKeyExchange:客户端生成预主密钥,用服务器公钥加密后发过去。
- ChangeCipherSpec:双方切换加密模式。
- Finished:双方发一条加密的验证消息,确认握手成功。
注意:ChangeCipherSpec 在 TLS 1.3 里被移除了。如果你还在用 TLS 1.2,记得检查服务器是否支持 Session Resumption,能省一次完整握手。
TLS 1.3 的握手就简洁多了,只需要 1-RTT:
- 客户端直接发 ClientHello + 密钥共享参数
- 服务器回复 ServerHello + 证书 + 完成消息
- 双方立刻就能发加密数据
我曾经帮一个视频直播平台做优化,从 TLS 1.2 切到 1.3,首屏加载时间降了 35%。说白了,少一次往返就是快。
1.4 TLS 记录协议概述:数据怎么打包上路?
握手完了,数据怎么传?这就轮到记录协议上场了。它负责把应用层数据切成小块,压缩(可选)、加 MAC、加密,然后扔给 TCP 发出去。
记录协议的结构其实很简单,就 5 个字段:
| 字段 | 长度 | 说明 |
|---|---|---|
| Content Type | 1 字节 | 标识记录类型(20=ChangeCipherSpec, 21=Alert, 22=Handshake, 23=Application Data) |
| Protocol Version | 2 字节 | TLS 版本号,如 0x0303 表示 TLS 1.2 |
| Length | 2 字节 | 负载长度,最大 2^14 字节(16384) |
| Payload | 可变 | 实际数据,可能包含 MAC 和填充 |
| MAC(可选) | 可变 | 消息认证码,TLS 1.3 中由 AEAD 替代 |
你可能会问:「为什么最大只有 16KB?」其实这是 TCP 的 MTU 限制决定的。我见过有人把记录设得太大,结果 IP 分片导致性能暴跌。嗯,这里要注意:记录大小最好控制在 1400 字节以内,避免分片。
实战技巧:抓包时看到 TLS 记录长度超过 16384,那一定是实现有 bug。我曾经排查过一个性能问题,发现某开源库把记录长度写成了 65535,结果接收端直接崩了。
记录协议在 TLS 1.3 里做了简化:
- 移除了压缩功能(压缩 + 加密 = CRIME/BREACH 攻击的温床)
- MAC 和加密合并为 AEAD(Authenticated Encryption with Associated Data)
- Content Type 被加密,中间人看不到你传的是握手消息还是应用数据
说白了,TLS 1.3 的记录协议更安全、更简洁。我建议新项目直接上 TLS 1.3,别在 1.2 上纠结了。