0x00 简介
SSL/TLS是一种密码通信框架。TLS(Transport Layer Security 传输层安全协议)实际上是 SSL(Secure Sockets Layer 安全套接层)的继承与标准化版本,两者在核心功能上是一脉相承的,但技术上并不完全兼容。
- 1994年,网景公司(Netscape)为了保障其浏览器与服务器之间的数据传输安全,开发了 SSL 1.0(未公开发布)
- 1995年发布了 SSL 2.0(存在严重安全漏洞)
- 1996年发布了 SSL 3.0。SSL 3.0是 TLS 1.0 的直接前身
- 1999年,互联网工程任务组(IETF)接手了协议的标准化工作,正式发布了 TLS 1.0
- 2006年,发布了 TLS 1.1,修补了若干安全漏洞
- 2008年,发布了 TLS 1.2,支持更强大的加密套件,目前较为广泛使用
- 2018年,发布了 TLS 1.3,大幅简化握手过程,并移除了所有的不安全的加密算法,安全性更高
因为SSL协议与TLS1.0/1.1已经废弃,所以本篇博客只讲TLS1.2与TLS1.3的协议架构
0x01 TLS协议架构
TLS 协议由底层的记录协议(Record Protocol) 和其承载的四种内容类型组成:握手协议(Handshake Protocol)、密码规格变更协议(Change Cipher Spec Protocol)、警告协议(Alert Protocol) 和应用数据协议(Application Data Protocol)。其中前三者协同完成安全连接的建立。
我们可以看到,不同的TLS数据包有着相同的结构,底层的Record Protocol,加上一个子协议,再加上一个消息类型
握手协议 HandShake Protocol
content type:22 0x16
核心职责
在客户端和服务器之间协商安全参数,验证双方身份,并生成共享的会话密钥(Session Key)。
主要功能
- 协议版本协商:客户端告知支持的 TLS 最高版本,服务器选择最终版本
- 密码套件协商:客户端列出支持的加密算法组合,服务器选择一个
- 密钥交换:通过 RSA 或 ECDHE 等方式,安全地生成 Pre-Master Secret
- 身份认证:服务器(可选客户端)通过数字证书证明身份
- 握手完整性验证:通过 Finished 消息确认整个握手过程未被篡改
消息类型
| 类型码 | 消息名称 | 发送方 | 作用 |
|---|---|---|---|
| 1 | Client Hello | 客户端 | 发起握手,发送版本、随机数、密码套件清单 |
| 2 | Server Hello | 服务器 | 回应协商结果,选择版本、密码套件 |
| 11 | Certificate | 服务器/客户端 | 发送数字证书链 |
| 12 | Server Key Exchange | 服务器 | 发送临时 DH 公钥等密钥交换参数(可选) |
| 13 | Certificate Request | 服务器 | 请求客户端发送证书(双向认证时) |
| 14 | Server Hello Done | 服务器 | 表示服务器初始消息发送完毕 |
| 15 | Certificate Verify | 客户端 | 证明客户端拥有证书对应的私钥(双向认证时) |
| 16 | Client Key Exchange | 客户端 | 发送密钥交换材料(加密的 Pre-Master 或临时公钥) |
| 20 | Finished | 服务器/客户端 | 验证握手完整性,是握手阶段第一条加密消息 |
TLS 1.3 的变化
- 合并了 Server Key Exchange 和 Certificate 的消息内容
- 移除了 Change Cipher Spec 协议(不再需要)
- 除 Client Hello 外,所有握手消息均加密
- 握手从 2-RTT 减少到 1-RTT
密码规格变更协议 Change Cipher Spec Protocol
content type:20 0x14
核心职责
通知对方,从下一条消息开始,将使用刚刚协商好的加密算法和密钥进行通信。
工作原理
TLS 协议在内部维护两个加密状态:
- 当前状态(current state):正在使用的加密参数(握手完成前为 null 加密)
- 挂起状态(pending state):刚刚协商好的新加密参数(尚未启用)
发送 Change Cipher Spec 的瞬间,当前状态参数变为挂起状态参数。此后,发送方发送的所有消息都会使用新密钥加密。
TLS 1.3 的变化
TLS 1.3 完全移除了 Change Cipher Spec 协议。原因:
- 握手过程大幅简化,不再需要显式的切换信号
- 加密范围扩展到整个握手过程(Client Hello 除外),切换时机隐式确定
警告协议 Alert Protocol
content type:21 0x15
核心职责
在 TLS 连接过程中报告错误、异常或状态变化。
消息结构
每条警告消息固定 2 个字节:
1 | struct { |
严重级别
| 值 | 级别 | 含义 | 行为 |
|---|---|---|---|
| 1 | warning | 警告 | 连接可继续(如 close_notify) |
| 2 | fatal | 致命错误 | 发送后必须立即断开连接 |
常见描述类型
| 值 | 描述 | 级别 | 含义 |
|---|---|---|---|
| 0 | close_notify | warning | 正常关闭连接(不是错误) |
| 10 | unexpected_message | fatal | 收到了不该收到的消息 |
| 20 | bad_record_mac | fatal | 解密或 MAC 校验失败 |
| 21 | decryption_failed | fatal | 解密失败(已废弃,易受攻击) |
| 40 | handshake_failure | fatal | 握手协商失败 |
| 42 | bad_certificate | warning | 证书损坏或无效 |
| 43 | unsupported_certificate | warning | 不支持的证书类型 |
| 44 | certificate_revoked | warning | 证书已被吊销 |
| 45 | certificate_expired | warning | 证书已过期 |
| 46 | certificate_unknown | warning | 证书其他问题 |
| 47 | illegal_parameter | fatal | 参数非法 |
| 48 | unknown_ca | fatal | 未知的 CA(证书链不完整) |
| 49 | access_denied | fatal | 访问被拒绝 |
| 70 | protocol_version | fatal | 协议版本不匹配 |
| 71 | insufficient_security | fatal | 安全级别不足 |
| 86 | certificate_required | fatal | 需要客户端证书但未提供 |
| 112 | no_application_protocol | fatal | ALPN 协商失败 |
应用数据协议 Application Data Protocol
content type:23 0x17
核心职责
承载上层应用的真实数据(如 HTTP 请求/响应、FTP 数据、邮件内容等)。
0x02 TLS握手
这一章将会介绍 TLS 协议的握手过程
TLS 1.2 握手过程
-
第一个发起握手的数据包由客户端发出,用于协商版本、密码套件等信息
Handshake Protocol: Client Hello
- Version:发送可用版本号
- Random(客户端随机数):由客户端生成的随机数,用来生成对称密钥
- 在 TLS 1.2 中,最终用于加密数据的 Master Secret 是由 Pre-Master Secret、固定标签"Master Secret"、双方随机数的拼接(Client Random + Server Random)通过伪随机函数(PRF)计算得出的。然后,Master Secret 又会结合 Client Random 和 Server Random,派生出实际加密数据的对称加密密钥、初始化向量(IV)、消息认证码密钥(MAC Key)
- 随机数的前 4 字节为时间戳,后 28 字节由操作系统提供的密码学安全伪随机数生成器(CSPRNG)生成
-
Cipher Suites:可用的密码套件清单
-
Compression Methods:可用的压缩方式清单
- 该字段是 TLS 1.2 及以前版本中,用于协商在加密前是否压缩应用数据的一个字段。2012 年的 CRIME 攻击证明 TLS 压缩是致命的,所有现代实现都禁用了它。你看到的清单里只有 null 一个选项,且很多抓包工具为了界面简洁,默认不展开显示这个单一值的字段。在 TLS 1.3 已经删除了这一字段
- Extensions:扩展字段
-
第二个数据包由服务器端发出,用于确认版本、密码套件等信息
Handshake Protocol: Server Hello
- Version:发送使用的版本号
- Random(服务器随机数):由服务器端生成的随机数,用来生成对称密钥
- Cipher Suite:使用的密码套件
- Compression Method:使用的压缩方式
- Extensions:扩展字段
Handshake Protocol: Certificate:服务器发送自己的证书链
Handshake Protocol: Server Key Exchange:当服务器的证书不包含足够的信息来完成密钥交换时,由服务器额外发送自己的密钥交换参数
Handshake Protocol: Server Hello Done:告诉客户端消息结束了
-
第三个数据包由客户端发出,用于发送自己的密钥交换参数
Handshake Protocol: Client Key Exchange:客户端发送自己的密钥交换参数
Change Cipher Spec Protocol: Change Cipher Spec:表示客户端之后的消息进行加密
Handshake Protocol: Finished:客户端握手协议结束,我们在实际抓包过程中可能看不到这个消息,因为已经被加密了,抓包工具解析不了
-
第四个数据包由服务器端发出,用于发送自己的密钥交换参数
Change Cipher Spec Protocol: Change Cipher Spec:表示服务器之后的消息进行加密
Handshake Protocol: Finished:服务器握手协议结束
TLS 1.3 握手过程
TLS 1.3(RFC 8446)大幅简化了握手流程。虽然你会在抓包中看到 Change Cipher Spec 消息,但这是为了兼容中间设备(防火墙、负载均衡器等)而发送的无实际作用的填充包,不是 TLS 1.3 协议本身需要的步骤。
-
TLS 1.3 的数据包不再发送 Compression Methods,通过 key_share 扩展,提前发送临时公钥,减少了一次往返
Handshake Protocol: Client Hello
-
服务器响应
Handshake Protocol: Server Hello
Handshake Protocol: Encrypted Handshake Message:从这条消息开始,所有后续消息都已加密。它实际包含以下多条握手子消息:
- Encrypted Extensions:服务器发送其他扩展
- Certificate:服务器发送自己的证书链
- Certificate Verify:服务器发送自己的证书验证信息
- Finished:服务器发送第一条加密后的握手验证消息,确认握手完整性
-
最后客户端发送 Finished 消息
Handshake Protocol: Finished