1. TLS协议基础:从SSL到TLS的演进

说到TLS,我得先聊聊它的前身——SSL。我入行那会儿,SSL 3.0还是主流,后来爆出了POODLE漏洞,整个行业才被迫全面迁移到TLS。说白了,TLS就是SSL的升级版,只是改了个名字。

1.1 TLS/SSL发展史

这张表我建议你记一下,面试和排障时经常用到:

版本 发布时间 状态 关键事件
SSL 2.0 1995 已废弃 存在严重安全缺陷
SSL 3.0 1996 已废弃 POODLE攻击后退役
TLS 1.0 1999 已废弃 实质是SSL 3.1
TLS 1.1 2006 已废弃 增加CBC保护
TLS 1.2 2008 广泛使用 当前主力版本
TLS 1.3 2018 推荐使用 握手大幅简化
避坑提醒: 我曾经在客户现场遇到过一台老服务器只支持SSL 3.0,现代浏览器全部拒绝连接。最后只能升级中间件版本。所以生产环境务必禁用SSL 2.0/3.0和TLS 1.0。

1.2 TLS握手协议概述

握手协议是整个TLS的核心。你想想看,客户端和服务器第一次见面,怎么互相确认身份?怎么商量用什么加密算法?怎么生成只有他俩知道的密钥?这些全在握手阶段完成。

我用Wireshark抓包时,最喜欢看的就是握手过程。一个正常的TLS 1.2握手,大概长这样:

  1. ClientHello — 客户端打招呼,告诉服务器自己支持哪些TLS版本、密码套件
  2. ServerHello — 服务器从列表里挑一个,回复确认
  3. Certificate — 服务器把自己的数字证书发给客户端
  4. ServerKeyExchange — 如果是DHE/ECDHE密钥交换,服务器发临时公钥
  5. ServerHelloDone — 服务器说"我这边发完了"
  6. ClientKeyExchange — 客户端发自己的密钥交换参数
  7. ChangeCipherSpec — 双方切换加密通信
  8. Finished — 握手完成确认

我的经验: 排障时先看ClientHello和ServerHello。如果客户端发了一堆密码套件,服务器却回了"握手失败",八成是版本不匹配或者证书有问题。我遇到过最坑的一次,是服务器时钟差了两年,证书验证直接挂了。

下面是TLS 1.2完整握手的流程图,我画出来方便你对照抓包看:

TLS 1.2 完整握手流程 客户端 服务器 ① ClientHello(版本+密码套件+随机数) ② ServerHello(选定版本+密码套件) ③ Certificate(服务器证书链) ④ ServerKeyExchange(DH公钥+签名) ⑤ ServerHelloDone ⑥ ClientKeyExchange(DH公钥) ⑦ ChangeCipherSpec(切换加密) ⑧ Finished(握手完整性校验)

抓包小技巧: 在Wireshark里过滤 tls.handshake.type == 1 可以快速定位ClientHello。我个人习惯先看ClientHello里的Cipher Suites长度,如果超过200字节,说明客户端支持了一大堆套件,这时候服务器选错套件的概率反而低。

1.3 TLS记录协议概述

握手协议搞定之后,真正的数据就开始传输了。记录协议就是负责把应用层数据(比如HTTP请求)切分成小块,加密后塞进TCP报文里发出去。

每个TLS记录的结构其实很简单:

  • 内容类型(1字节)— 是握手消息、警报还是应用数据
  • 协议版本(2字节)— 比如TLS 1.2是0x0303
  • 长度(2字节)— 后面负载的长度
  • 负载(可变长度)— 加密后的数据或明文握手消息

嗯,这里要注意:TLS 1.3里记录协议有了变化,握手阶段的ChangeCipherSpec被移除了,但应用数据的加密方式更统一了。

1.4 密码套件概念

密码套件(Cipher Suite)说白了就是一组算法的组合。我经常跟新人说,你把它想象成一个"安全套餐"——里面包含了密钥交换、身份认证、对称加密和消息完整性校验这四样东西。

举个例子,一个常见的TLS 1.2密码套件长这样:

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

拆开来看:

组成部分 示例值 作用
密钥交换 ECDHE 协商临时密钥,保证前向安全性
身份认证 RSA 用RSA签名验证服务器身份
对称加密 AES_128_GCM 实际加密数据,GCM模式同时提供完整性
PRF/哈希 SHA256 用于密钥派生和Finished校验

我的建议: 生产环境优先选择支持前向安全性的套件,也就是ECDHE或DHE开头的。我曾经审计过一个系统,用的还是TLS_RSA_WITH_AES_128_CBC_SHA,一旦私钥泄露,所有历史流量都能被解密。后来我帮他们切到了ECDHE,才算放心。

在Wireshark里,你可以在ServerHello的Cipher Suite字段看到最终选定的套件。如果发现服务器选了一个弱套件(比如RC4或CBC模式的),赶紧查一下服务器配置——八成是配置里把强套件排到了后面。

最后说一句,TLS 1.3把密码套件简化了很多,不再支持那些过时的算法。比如RSA密钥交换被彻底移除了,因为不支持前向安全性。你想想看,连RFC都直接砍掉了,说明这玩意儿确实该退休了。