TLS 协议基础与演变
3.1 TLS 在安全体系中的定位
TLS 协议到底是什么?说实话,很多工程师学了几年网络,还是把它跟 HTTPS 划等号。其实 TLS 是独立于应用层的安全传输协议。
我个人更愿意把 TLS 理解成一个“安全管道工厂”。它不关心你传的是 HTTP、FTP 还是自定义协议。它只负责两件事:一是证明对方身份,二是加密通信内容。我记得刚开始做 TLS 协议分析时,总觉得它很复杂。后来才发现,核心就这四个服务:机密性、完整性、身份认证、防重放。
| 安全服务 | TLS 实现方式 | 我踩过的坑 |
|---|---|---|
| 机密性 | 对称加密(握手阶段协商算法和密钥) | 用 AES-GCM 时忘记更新 Nonce,导致加密出错 |
| 完整性 | MAC(消息认证码)或 AEAD 模式 | 早期项目用的 CBC + HMAC,容易被 BEAST 攻击 |
| 身份认证 | 数字证书 + 非对称签名 | 证书链验证不完整,中间人攻击轻松绕过 |
| 防重放 | 序列号 + 随机数(TLS 1.3 用隐式序列号) | 国密改造时忘了处理序列号窗口,导致丢包重连频繁 |
实际上,TLS 并不是加密传输的唯一选择。IPsec 也在网络层做加密,SSH 则在应用层做隧道。但 TLS 在互联网生态中的普及度最高,原因很简单:浏览器支持、标准成熟、适配灵活。
我在项目中遇到过一个取巧的设计——有人把敏感业务直接跑在 TCP 上,前面加一层自定义加密。结果是什么?每次改密算法都要改客户端和服务端两端代码,维护成本翻倍。所以我的建议是:除非你有极致的性能要求,否则别自己造 TLS 轮子。
3.2 TLS 协议框架:两个核心协议
TLS 由两条“轨道”组成,一条跑控制信号,一条跑业务数据。你想想看,这跟操作系统里的内核态和用户态很像。握手协议负责协商密钥和算法,记录协议负责实际加密传输。
3.2.1 握手协议
握手协议是 TLS 最复杂的部分。它要完成:协商版本、交换随机数、验证身份、生成主密钥。TLS 1.2 需要两次往返(2-RTT),TLS 1.3 缩减到一次往返(1-RTT)。嗯,这里要注意,国密套件的握手流程跟国际标准有差异,后面我会专门讲。
我记得第一次调通 TLS 握手时,看到抓包文件里 ClientHello、ServerHello、Certificate、ClientKeyExchange 一整套交互,感觉像是在看一份加密版的“外交协议”。
3.2.2 记录协议
记录协议就简单多了。它把上层数据分成片段,压缩(可选)、加 MAC、加密,然后封装成 TLS 记录发出。收端做逆操作。为什么会设计成两层?说白了是为了复用。握手完成后,业务数据直接走记录协议,不需要再反复协商密钥。
一个小技巧:调试 TLS 问题时,优先看握手阶段的报文。记录协议加密后你看不懂,但握手阶段的 Certificate 和 ServerHello 是明文的(至少部分字段是)。拿 Wireshark 抓包,配合 (pre)-master-secret log 就能解密。
我在项目中遇到过 MTU 分片导致握手失败的问题。TLS 记录最大是 16KB,但底层 TCP 的 MSS 只有 1460 字节左右。如果证书链特别长(比如 4 级 CA),Certificate 消息可能超过 16KB 限制,导致连接断开。解决办法?要么缩短证书链,要么在服务端启用 TLS 分片扩展。
3.3 TLS 版本演进:从 SSL 到 TLS 1.3
很多人分不清 SSL 和 TLS。其实 SSL 是 Netscape 在 90 年代搞的,后来 IETF 接手后改名为 TLS。名字变了,但 DNA 没变。我建议你不要再写“SSL/TLS”这种模糊说法了,2024 年的项目就直接说 TLS。
| 版本 | 发布时间 | 核心变化 | 我的态度 |
|---|---|---|---|
| SSL 2.0 | 1995 | 第一个公开版本,安全性极差 | 别碰 |
| SSL 3.0 | 1996 | 引入 HMAC,修复很多漏洞 | POODLE 攻击后已废弃 |
| TLS 1.0 | 1999 | RFC 2246,改名为 TLS | 可被 BEAST 攻击,建议关闭 |
| TLS 1.1 | 2006 | 增加 CBC 防御机制 | 安全但低效,已过时 |
| TLS 1.2 | 2008 | RFC 5246,支持 GCM/CCM | 当前主力,国密首选 |
| TLS 1.3 | 2018 | RFC 8446,1-RTT,移除不安全算法 | 强烈推荐,但国密支持有限 |
曾经有一家金融客户找我做安全审计,他们还在用 TLS 1.0。理由是“老系统不敢动”。我当场演示了 BEAST 攻击代码,25 秒内就解出了加密 Cookie。嗯,从那以后他们当天就申请升级了。
TLS 1.3 最大的变化是精简了握手流程,从 2-RTT 降到 1-RTT,并且支持 0-RTT 快速恢复。为什么要砍掉那么多密码套件?你想想看,TLS 1.2 有 37 种密码套件,大部分没人用,还容易留坑。TLS 1.3 只保留 5 种,全是 AEAD 模式,彻底消除了 CBC 模式下的时序攻击隐患。
但 TLS 1.3 也有代价。它对中间件设备(如防火墙、负载均衡)不友好。这些设备需要解密流量做安全检测,TLS 1.3 的加密握手让它们无法轻易拆包。另外,国密算法在 TLS 1.3 中的标准化工作还没完全结束,所以当前国密项目的主流选择还是 TLS 1.2。
3.4 DTLS:当 TLS 遇上 UDP
有些场景不能用 TCP,比如视频通话、物联网传感器上报。TLS 依赖 TCP 的可靠传输和有序性,不能直接用。DTLS(Datagram TLS)就是为解决这个问题诞生的。它在 TLS 基础上增加了序列号、重传机制、分片重组等逻辑,但保持了跟 TLS 相近的安全强度。
我在做视频会议平台的国密改造时,就遇到了 DTLS 的问题。标准 DTLS 支持的是国际算法,国密 DTLS 的实现还不太成熟。我们当时选了折中方案:信令走 TLS 加密,媒体流走 SRTP(使用国密 SM4 加密)。
这里有个容易犯的错:DTLS 的握手超时跟 TCP 完全不同。TCP 有内核帮我们做重传,DTLS 要应用层自己管理超时和重传。有过一个工程师把 DTLS 超时设为 10 秒,丢一个握手包要等 10 秒才重试,用户体验极差。我建议 DTLS 的初始超时设在 100ms 左右,按指数退避增长,最大不超过 1 秒。
3.5 本章知识体系:一张图看懂
下面我用一张 SVG 图把 TLS 协议体系串起来。这张图是我做培训时最常用的,学员反馈说“比看 RFC 三小时都管用”。放心,它不复杂,就是四个层次从下往上递进。
从这个图你能看到,TLS 协议体系是层层递进的。应用层数据先被握手协议处理(协商参数、验证身份),然后交给记录协议加密打包,最后通过 TCP 或 UDP 发出去。国密改造要动的主要是握手协议中的密码套件和证书格式,记录协议的加密算法换一下就行,整体框架不动。