1. TLS 协议基础:发展历史、握手协议、记录协议与密码套件

聊 TLS 加固,得先把地基打牢。我见过不少团队,上来就配一堆高级密码套件,结果握手都失败——说白了,连 TLS 怎么工作的都没搞清楚。这一章,我们从头捋一遍。

1.1 TLS 发展历史:从 SSL 到 TLS 1.3

TLS 的前身是 SSL,网景公司搞的。后来 IETF 接手,改名叫 TLS。嗯,这里有个坑:很多人把 SSL 和 TLS 混着叫,其实 TLS 1.0 就是 SSL 3.0 的升级版。

版本 发布年份 关键变化 现状
SSL 2.0 1995 第一个公开版本,漏洞太多 已废弃
SSL 3.0 1996 修复了主要安全问题 已废弃(POODLE 攻击)
TLS 1.0 1999 基于 SSL 3.0,改名换姓 已废弃(BEAST 攻击)
TLS 1.1 2006 增加 CBC 保护,防 IV 预测 已废弃
TLS 1.2 2008 支持 AEAD,灵活密码套件 广泛使用
TLS 1.3 2018 精简握手,移除不安全算法 推荐使用
我的建议:新项目直接上 TLS 1.3。如果兼容老客户端,至少 TLS 1.2 起步。SSL 和 TLS 1.0/1.1 就别开了——我在一次安全审计中见过某金融系统还开着 TLS 1.0,结果被 BEAST 攻击打了个正着。

1.2 TLS 握手协议:连接是怎么建立的?

握手协议是 TLS 最核心的部分。说白了,就是客户端和服务器互相确认身份、协商加密参数的过程。我习惯把它分成四个阶段:

  1. ClientHello:客户端发个招呼,告诉服务器自己支持哪些 TLS 版本、密码套件、扩展。
  2. ServerHello + 证书:服务器选一个双方都支持的套件,发回证书(证明自己是谁)。
  3. 密钥交换:双方用非对称加密交换一个预主密钥,然后各自算出会话密钥。
  4. Finished:双方确认握手完成,之后所有数据都用对称加密传输。

你想想看,这个过程其实挺巧妙的——用非对称加密来安全地交换对称密钥,既保证了安全性,又兼顾了性能。

避坑指南:我曾经遇到过一个案例,客户端和服务器的密码套件列表完全不重叠,握手直接失败。排查了半天,发现是服务器只配了 ECDHE 套件,而客户端只支持 RSA 密钥交换。所以,密码套件的兼容性一定要提前规划好。

下面是 TLS 1.2 完整握手的流程图,我画了一个简化版:

TLS 1.2 完整握手流程 客户端 服务器 ClientHello ServerHello + 证书 ClientKeyExchange ChangeCipherSpec ChangeCipherSpec 加密应用数据 加密应用数据 客户端发送支持的 TLS 版本、密码套件列表 服务器选择套件,发回证书和公钥 客户端用服务器公钥加密预主密钥

1.3 TLS 记录协议:数据是怎么传输的?

握手完成后,所有应用数据都通过记录协议传输。记录协议做的事情其实很简单:

  • 分片:把应用数据切成不超过 2^14 字节的片段。
  • 压缩:TLS 1.2 支持压缩,但 TLS 1.3 移除了(因为 CRIME 攻击)。
  • 加密:用协商好的对称密钥加密每个片段。
  • MAC:添加消息认证码,防止篡改。
  • 封装:加上记录头(内容类型、版本、长度),发送出去。

记录协议的核心结构:

struct {
    ContentType type;       // 内容类型(20=ChangeCipherSpec, 21=Alert, 22=Handshake, 23=Application Data)
    ProtocolVersion version; // TLS 版本
    uint16 length;          // 负载长度
    opaque fragment[TLSPlaintext.length]; // 加密后的数据
} TLSPlaintext;

我个人觉得,记录协议最容易被忽视的是 序列号。每个方向(客户端→服务器、服务器→客户端)都有一个独立的 64 位序列号,用于防止重放攻击。嗯,这个细节在调试时很有用——如果你看到 MAC 校验失败,多半是序列号对不上。

1.4 密码套件概念:到底在协商什么?

密码套件(Cipher Suite)是一组算法的组合。TLS 握手时,双方要协商出一套大家都支持的套件。一个典型的密码套件长这样:

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

拆开来看,它包含四个部分:

组件 示例值 作用
密钥交换算法 ECDHE 安全地交换对称密钥(前向安全性)
身份认证算法 RSA 验证服务器身份(证书签名)
对称加密算法 + 模式 AES_256_GCM 加密实际传输的数据
HMAC 哈希算法 SHA384 消息完整性校验
我曾经踩过的坑:有次配置 Nginx,我用了 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,结果安全扫描报告说 CBC 模式容易受 Lucky13 攻击。后来我全部换成了 GCM 模式的 AEAD 套件。所以,我建议你优先选择 GCM 或 ChaCha20-Poly1305 这类认证加密模式。

你想想看,密码套件的选择直接影响安全性。TLS 1.3 在这方面做了简化——移除了所有不安全的算法(比如 RC4、3DES、CBC 模式),只保留了 5 个强套件。这也是为什么我推荐直接上 TLS 1.3 的原因之一。

1.5 小结

这一章我们覆盖了 TLS 的四个基础概念:发展历史、握手协议、记录协议和密码套件。说白了,TLS 的核心就是两件事:握手协商(用非对称加密安全地交换对称密钥)和 记录保护(用对称加密安全地传输数据)。

后面的章节,我们会基于这些基础,一步步深入到具体的加固方案中。嗯,先把这些概念吃透,后面才不会迷路。