2. TLS协议基础:从SSL到TLS的演进与协议分层
聊TLS之前,我想先说说我早年的一次经历。那时候我刚入行,公司有个电商项目,用户反馈登录时经常卡顿,甚至偶尔会提示"连接不安全"。我抓了包一看,发现还在用SSL 3.0——那会儿已经是2014年了,距离POODLE漏洞曝光才过去几个月。嗯,从那以后,我对TLS版本这件事就特别敏感。
2.1 TLS/SSL发展史:一个关于安全的进化故事
SSL(Secure Sockets Layer)最早是网景公司在1994年推出的。说白了,就是为了解决HTTP明文传输的安全问题。你想想看,早期的互联网就像在明信片上写密码,谁都能看。SSL就是给这张明信片加了个信封。
版本演进其实不复杂,我整理了一张表:
| 版本 | 发布时间 | 状态 | 关键事件 |
|---|---|---|---|
| SSL 1.0 | 1994(未公开) | 废弃 | 存在严重安全问题,从未正式发布 |
| SSL 2.0 | 1995 | 废弃(2011年RFC 6176) | 无法抵御中间人攻击,我见过老系统还在用 |
| SSL 3.0 | 1996 | 废弃(2015年RFC 7568) | POODLE漏洞,我亲手帮客户升级过 |
| TLS 1.0 | 1999(RFC 2246) | 废弃(2021年RFC 8996) | 实际上是SSL 3.0的升级版,改名是为了规避专利 |
| TLS 1.1 | 2006(RFC 4346) | 废弃(2021年RFC 8996) | 增加了CBC保护,但改进有限 |
| TLS 1.2 | 2008(RFC 5246) | 广泛使用 | 支持GCM/CCM,SHA-256,目前主流 |
| TLS 1.3 | 2018(RFC 8446) | 推荐使用 | 握手从2-RTT降到1-RTT,移除不安全算法 |
核心观点:我个人建议,新项目直接上TLS 1.3。如果兼容性有要求,至少也要TLS 1.2。SSL 2.0/3.0和TLS 1.0/1.1已经全部被RFC废弃了,别再用。
2.2 TLS在OSI模型中的位置:夹在中间的那个"胶水层"
这个问题我面试时经常问。很多人会答错,觉得TLS是网络层或者表示层。其实TLS的位置很特殊——它工作在传输层和应用层之间。
来看这张图,我画了一个OSI模型的分层示意:
为什么TLS要放在这个位置?原因很简单:它既要利用TCP的可靠传输,又要为上层应用提供安全服务。你想想看,如果TLS放在网络层,那它就得处理IP分片和路由问题,太复杂了。如果放在应用层,每个应用都得自己实现加密,太混乱。
小技巧:在Wireshark里抓TLS包时,你会看到TCP三次握手完成后,紧接着就是TLS握手。这就是"先建连接,再建安全"的典型流程。我习惯先看TCP的SYN/SYN-ACK/ACK,再看Client Hello,这样能快速定位问题出在传输层还是安全层。
2.3 TLS握手协议与记录协议:两个核心"零件"
TLS协议其实不是单个协议,而是一个协议族。最核心的两个子协议是:握手协议(Handshake Protocol)和记录协议(Record Protocol)。打个比方,握手协议是"谈条件",记录协议是"干活"。
2.3.1 握手协议:谈条件的过程
握手协议负责在客户端和服务器之间协商安全参数。说白了,就是双方坐下来谈:用什么加密算法?用什么密钥?你信不信我?
握手协议的主要步骤(以TLS 1.2为例):
- Client Hello:客户端告诉服务器自己支持的TLS版本、密码套件列表、随机数等。
- Server Hello:服务器从客户端列表里选一套,回复自己的随机数和证书。
- Certificate:服务器发送数字证书(包含公钥)。
- Server Key Exchange(可选):如果需要,服务器发送额外的密钥交换参数。
- Client Key Exchange:客户端生成预主密钥,用服务器公钥加密后发送。
- Change Cipher Spec:双方通知对方"我要开始加密了"。
- Finished:双方发送加密后的握手消息摘要,验证握手是否被篡改。
注意:我曾经遇到过一个案例,客户说"TLS握手总是失败"。我抓包一看,发现服务器返回的证书是自签名的,客户端没有信任这个CA。这就是Certificate步骤出了问题。所以排查握手问题时,先看证书链是否完整。
2.3.2 记录协议:干活的流程
握手完成后,真正的数据传输就交给记录协议了。记录协议做的事情很简单:把应用层数据分片、压缩(可选)、加密、加上MAC(消息认证码),然后交给TCP发送。
记录协议的格式非常固定,我拆解一下:
| 字段 | 长度 | 说明 |
|---|---|---|
| Content Type | 1字节 | 标识上层协议类型:20=ChangeCipherSpec, 21=Alert, 22=Handshake, 23=Application Data |
| Protocol Version | 2字节 | TLS版本号,例如0x0303表示TLS 1.2 |
| Length | 2字节 | 负载数据的长度(不超过2^14字节) |
| Payload | 可变 | 实际数据,可能是握手消息、告警或加密后的应用数据 |
在Wireshark里看记录协议特别直观。你展开一个TLS包,第一层就是"TLSv1.2 Record Layer",里面清清楚楚地写着Content Type、Version、Length。我个人习惯先看Content Type,如果是23(Application Data),说明握手已经完成,正在传真正的数据。
2.3.3 握手协议 vs 记录协议:一张图看懂
我画了张流程图,把这两个协议的关系和交互过程展示出来:
关键理解:握手协议是"一次性的",只在连接建立时运行。记录协议是"持续性的",每次数据传输都用它。在Wireshark里,你会看到握手阶段全是Content Type=22(Handshake)的包,握手完成后就变成Content Type=23(Application Data)了。这个变化非常明显,一眼就能看出来。
2.4 小结:为什么你要理解这些?
说实话,很多人觉得TLS协议基础太理论,不如直接上手抓包。但我的经验是,不理解握手协议和记录协议的区别,你在Wireshark里看到一堆TLS包时根本不知道从哪看起。比如,你看到Client Hello,就知道这是握手的开始;看到Application Data,就知道数据已经在加密传输了。