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

聊TLS连接复用之前,咱们得先把地基打牢。TLS/SSL这套协议,说白了就是给HTTP套了层加密外壳。我最早接触它是在2010年,那时候还在用SSL 3.0,后来才知道这玩意儿漏洞一堆。

你想想看,互联网最初设计的时候根本没考虑加密。HTTP明文传输,抓个包就能看到你的密码、cookie、信用卡号。后来网景公司实在看不下去了,1994年搞出了SSL 1.0——虽然没公开发布过。真正落地的是SSL 2.0(1995年)和SSL 3.0(1996年)。

嗯,这里要注意:SSL 3.0在2014年被曝出POODLE漏洞,现在已经彻底废弃了。我当年维护过一个老系统,升级TLS时发现还有客户端硬编码了SSL 3.0,折腾了好几天才全部迁移掉。

核心认知:TLS 1.0、1.1、1.2、1.3是IETF标准化后的版本。TLS 1.0相当于SSL 3.1,但两者不兼容。目前生产环境最低要求是TLS 1.2,TLS 1.3正在快速普及。

1.1 TLS握手协议——连接建立的"握手礼"

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

  1. Hello阶段:Client Hello + Server Hello,交换随机数、支持的密码套件、TLS版本
  2. 认证阶段:服务器发送证书(Certificate),客户端验证证书链
  3. 密钥交换阶段:根据密码套件,用RSA或DH系列算法生成预主密钥
  4. 完成阶段:双方确认握手消息完整性,开始加密通信

我在项目中遇到过一个问题:某电商平台用户登录时特别慢,抓包发现每次请求都重新握手。后来加了会话复用,延迟从800ms降到了50ms。这就是咱们这门课的核心价值。

实战技巧:用openssl s_client -connect example.com:443 -msg可以实时查看握手过程的每条消息。我排查TLS问题时,这个命令几乎每天都要用。

1.2 TLS记录协议——加密数据的"打包工"

握手完成后,真正的数据传输靠记录协议。它把应用层数据切成片段,然后压缩(可选)、加MAC、加密、添加记录头。每个记录最大16KB。

记录协议的结构很简单:

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

你想想看,为什么要有记录协议?因为TCP是流式协议,没有消息边界。记录协议就是给数据画上"分隔符",让接收方能正确还原应用层消息。我曾经调试过一个bug,客户端和服务器的最大片段长度(MSS)不匹配,导致大文件传输失败——最后发现是记录协议的分片逻辑写错了。

1.3 密码套件——加密算法的"组合套餐"

密码套件就是一组算法的集合,决定了握手怎么认证、密钥怎么交换、数据怎么加密、完整性怎么校验。它的命名规则很直观:

套件示例 密钥交换 认证 加密 MAC
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ECDHE RSA AES-128-GCM SHA-256
TLS_RSA_WITH_AES_256_CBC_SHA RSA RSA AES-256-CBC SHA-1
TLS_AES_128_GCM_SHA256 (TLS 1.3隐式) (TLS 1.3隐式) AES-128-GCM SHA-256

避坑指南:我曾经在生产环境遇到过一个问题——服务器配置了TLS_RSA_WITH_AES_256_CBC_SHA,结果被安全扫描工具报"Lucky13漏洞"。CBC模式在TLS 1.2及以下版本中容易受到padding oracle攻击。建议优先使用GCM或ChaCha20-Poly1305这类AEAD模式。

我个人习惯把密码套件分成三代:

  • 第一代(TLS 1.0/1.1):RSA密钥交换 + CBC加密 + SHA-1 MAC。现在基本都废弃了。
  • 第二代(TLS 1.2):ECDHE密钥交换 + GCM加密 + SHA-256。目前的主流选择。
  • 第三代(TLS 1.3):简化了密码套件,只保留5种AEAD组合。握手只需1-RTT。

为什么TLS 1.3要砍掉那么多套件?说白了,历史包袱太重。以前为了兼容性,支持了几十种算法组合,结果很多都有安全缺陷。TLS 1.3直接"断舍离",只保留最安全的选项。我在升级项目时,从TLS 1.2切到1.3,握手时间从2-RTT降到了1-RTT,页面加载快了将近一倍。

1.4 知识体系总览

下面这张图把TLS协议的核心脉络串起来了。我每次给团队做培训都会画一遍——理解了这张图,TLS就算入门了。

TLS协议核心知识体系 TLS协议核心知识体系 TLS协议 握手协议 记录协议 密码套件 Client Hello / Server Hello 证书验证 / 密钥交换 ChangeCipherSpec / Finished 分片 / 压缩 MAC计算 / 加密 记录头封装 / 发送 密钥交换算法(ECDHE/RSA) 加密算法(AES-GCM/ChaCha20) MAC算法(SHA-256/Poly1305) 说明 握手协议建立安全连接 → 记录协议传输加密数据 → 密码套件决定具体算法组合

这张图里,握手协议负责"打招呼"和"交换钥匙",记录协议负责"打包发货",密码套件决定"用什么锁和钥匙"。三者配合,才构成了完整的TLS安全通道。

我的建议:刚开始学TLS时,别急着啃RFC。先抓包看一次完整的TLS握手——用Wireshark过滤tls.handshake.type,亲眼看到Client Hello、Server Hello、Certificate、Key Exchange、Finished这些消息,比看十遍文档都管用。

好了,这一章的基础知识就到这里。记住:TLS不是黑魔法,它就是一套精心设计的加密通信协议。理解了握手、记录、密码套件这三个核心概念,后面讲连接复用、会话缓存、0-RTT这些高级话题时,你就能快速抓住本质了。