第1章:TLS协议概述——从握手说起的加密旅程

各位好,我是你们的讲师。在正式开始配置合规性验证之前,咱们得先统一认知——TLS到底是个什么东西?

我见过不少运维同事直接把“TLS”和“SSL”混着用,甚至还有人觉得HTTPS就是TLS。其实这些概念之间差着辈分呢。今天这一章,我就带你从头捋一遍。

1.1 历史版本:SSL 死了,TLS 活着

故事要从1995年说起。网景公司搞了个叫 SSL 2.0 的东西,目的是让浏览器和服务器之间安全传数据。紧接着 1996 年出了 SSL 3.0,算是第一版广泛使用的安全协议。

后来 IETF 接手了这个活儿,在 1999 年发布了 TLS 1.0(其实本质就是 SSL 3.0 的升级版)。到这里名字换了,但核心框架没大变。

我个人习惯把版本演变画成一张表,你一看就明白:

版本 发布年份 状态 我个人的评价
SSL 2.0 1995 已废弃 漏洞多到像筛子,别碰
SSL 3.0 1996 已废弃(POODLE攻击后) 我当年刚入行时还在用它,后来被POODLE搞惨了
TLS 1.0 1999 已废弃 还能在老的Windows XP上见到
TLS 1.1 2006 已废弃 基本是个过渡版本,用得不多
TLS 1.2 2008 广泛使用 目前最稳的主力版本
TLS 1.3 2018 当前推荐 握手更快,更安全,强烈推荐
警告: 所有 SSL 版本(2.0/3.0)以及 TLS 1.0/1.1 都被明确标记为不安全,各大合规标准(PCI DSS、NIST)已强制禁用。千万不要在生产环境开启这些版本,我曾经在客户现场见过一个内部系统还在用 TLS 1.0,审计直接亮红灯。

1.2 从 SSL 到 TLS:名字改了,魂没变

TLS 和 SSL 到底有啥区别?说白了:

  • SSL(Secure Sockets Layer):网景的私有协议,早期版本混乱,后来被 IETF 标准化。
  • TLS(Transport Layer Security):IETF 接手后改的名字,本质上是 SSL 3.0 的演进版。

但要注意:TLS 1.0 内部版本号是 3.1,TLS 1.1 是 3.2,TLS 1.2 是 3.3。所以很多老库代码里还在用 “SSLv3.1” 这样的字符串来指代 TLS 1.0。你看到别懵。

我遇到过一件事:有一次排查 Nginx 日志,发现客户端报告 “SSLv3”,我第一反应是开了 SSlv3 漏洞。后来细查才发现,是 OpenSSL 的一个历史遗留 bug,把 TLS 1.0 握手记录标记成了 SSLv3。嗯,别被字面迷惑。

1.3 HTTPS 与 TLS 的关系:一个是车,一个是发动机

很多人以为 HTTPS 就是 TLS,这不太准确。我打个比方:

  • HTTP 是卡车(传输明文数据)
  • TLS 是发动机(加密保护)
  • HTTPS 就是装上了 TLS 发动机的 HTTP 卡车

所以 HTTPS = HTTP over TLS,本质是 HTTP 协议运行在 TLS 安全层之上。浏览器地址栏的绿色小锁,代表的是 TLS 握手成功、证书可信、会话加密。

提示: 配置 HTTPS 时,你实际配置的是 listen 443 ssl; 这类指令。Nginx 和 Apache 里所谓的 “SSL 配置”,其实配置的都是 TLS 协议参数。别再在配置文件里写 ssl_protocols TLSv1.2 TLSv1.3; 这种自我矛盾的写法了 —— 虽然正确,但看着别扭。

1.4 TLS 握手流程简介:一次加密的握手舞

TLS 握手的核心目标是什么?协商加密算法、验证对方身份、生成对称密钥。这个过程在我们看来是瞬间完成的,但背后其实挺复杂。

我先画一张完整的流程图,咱们一起走一遍:

TLS 1.2 完整握手流程 客户端 (Client) 浏览器/App 服务端 (Server) Nginx/Apache ① ClientHello (支持的加密套件、TLS版本等) ② ServerHello + Certificate (选定算法、发送证书、ServerHelloDone) ③ ClientKeyExchange (预主密钥加密传输 + ChangeCipherSpec + 客户端Finished) ④ Server ChangeCipherSpec + Finished (服务端通知加密开始,并发送Finished校验) ⑤ 应用数据加密传输 (真正的HTTP请求/响应,使用对称加密) 后续所有通信都是双向加密 说明: TLS 1.3 将步骤②③④合并为一次往返(1-RTT),大大缩短握手时间

我习惯把这个过程拆成5个关键步骤:

  1. ClientHello:客户端告诉服务器“我支持这些TLS版本,这些加密套件”。
  2. ServerHello + Certificate:服务器选择好版本和算法,把数字证书发给客户端。
  3. ClientKeyExchange:客户端用服务器公钥加密一个“预主密钥”发给服务器。
  4. ChangeCipherSpec + Finished:双方协商出对称密钥,并握手完成校验。
  5. 应用数据加密:之后所有通信都是用对称密钥加密的了。

重点: 第3步里那个“预主密钥”很关键。我记得有一次排查TLS握手失败,OpenSSL日志里报“premaster secret size mismatch”。最后发现是客户端用了不支持的密钥交换算法(比如DH参数长度不匹配)。所以配置合规性验证里,第一步就是要检查加密套件和密钥交换算法是否被正确禁用或启用。

1.5 一个真实案例:SSLv3 还在用,差点被审计毙了

2014年,POODLE攻击爆发,所有SSLv3瞬间变成高危。我接手过一个老系统的改造,Java 1.6 写的,负载均衡器还是 F5 BIG-IP 9.x,默认启用了 SSLv3。客户审计公司的报告写着“严重不符合PCI DSS v3.2要求”。

我当时和运维团队一块排查:先检查应用层有没有硬编码 TLS 版本,然后升级负载均衡固件,最后在 Nginx 端加上 ssl_protocols TLSv1.2 TLSv1.3;。整个改造花了两周,但结果就是:所有 SSLv3 都禁掉了,握手效率反而因为只用 TLS 1.2 以上变得更快了。

经验: 做合规性验证时,别只看协议版本。还要检查密钥长度、签名算法、证书链。我曾经见过一个配置:TLS 1.2 用了,但证书用的 SHA-1 签名,审计直接判定“不合规”。所以后面对每一层都要细查。

1.6 本章小结:我们为什么需要懂这些?

你可能会想:我只是配个 Nginx,知道这些历史干嘛?

我个人的体会是:不懂握手细节,你遇到奇怪的连接失败时根本没方向。比如客户端报告“handshake failure”,你至少要能猜到是版本协商失败还是证书验证失败,还是密钥交换参数不一致。

后面的课程里,我们会用到大量抓包分析(Wireshark + tshark),也会用 OpenSSL 命令手动测试。所以今天这章打底很重要。记住这几个关键点:

  • SSL 是旧名称,TLS 是标准名称,不要再混用。
  • HTTPS = HTTP over TLS,不是另起炉灶的新协议。
  • TLS 1.2 和 1.3 是当前唯二可用的版本。
  • 握手分5步,其中密钥交换和证书验证是核心。