1. TLS协议概述:从诞生到握手

聊TLS证书验证之前,咱们得先把TLS本身搞清楚。我见过不少开发同学,证书报错了就去搜“如何解决”,结果折腾半天发现是TLS版本不匹配——说白了,底层协议没理解透,上层问题根本无从下手。

这一章,我带你把TLS的来龙去脉、它在网络安全里的位置、以及最核心的握手流程过一遍。嗯,这些都是后面30章的基础,你想想看,如果连握手都说不清楚,后面讲证书链验证的时候你会很痛苦。

1.1 TLS的发展历史

TLS的前身是SSL,全称Secure Sockets Layer。最早是Netscape公司在90年代搞出来的。我记得刚入行那会儿,很多老系统还在用SSL 3.0,后来爆出POODLE漏洞,整个行业才被迫全面迁移到TLS。

来,看这张简表,帮你快速理清版本脉络:

协议版本 发布年份 状态 关键说明
SSL 1.0 未公开 废弃 从未正式发布,存在严重安全问题
SSL 2.0 1995 废弃 第一个公开版本,但漏洞太多
SSL 3.0 1996 废弃 POODLE攻击后彻底弃用
TLS 1.0 1999 废弃 实际上是SSL 3.0的升级版
TLS 1.1 2006 废弃 增加了CBC防御
TLS 1.2 2008 广泛使用 当前主力版本,支持AEAD
TLS 1.3 2018 推荐使用 大幅简化握手,移除不安全算法

核心建议:我个人习惯,新项目一律只开TLS 1.2和1.3。TLS 1.0/1.1和SSL全系列,直接禁用,别犹豫。

为什么TLS 1.3这么重要?因为它把握手从2-RTT降到了1-RTT,甚至0-RTT(虽然0-RTT有重放风险,后面会细讲)。我在一个高并发API网关项目里,光升级到TLS 1.3,握手延迟就降了40%。

1.2 TLS在网络安全中的角色

TLS不是银弹,但它解决了三个最基础的安全问题:

  • 机密性 — 数据在传输过程中是加密的,中间人看不到明文
  • 完整性 — 数据在传输过程中没有被篡改
  • 身份验证 — 你连接的服务端确实是它声称的那个实体

你想想看,如果没有TLS,你在咖啡厅连公共WiFi,输入密码的时候,隔壁桌的人用Wireshark就能直接抓到你的明文包。我曾经在安全培训课上做过演示,五分钟就抓到了一个测试站点的登录凭证——现场所有人都沉默了。

但这里有个容易忽略的点:TLS只保护传输层。数据到了服务端之后,TLS就管不了了。所以别以为上了HTTPS就万事大吉,应用层的漏洞TLS可不管。

避坑指南:我曾经遇到一个团队,他们把所有API都走了HTTPS,但内部微服务之间用的却是明文HTTP。结果攻击者通过内网横向移动,直接把数据库拖走了。记住,TLS应该覆盖所有网络边界,包括内部通信。

1.3 TLS握手协议基本流程

握手,是TLS最精彩的部分。客户端和服务端第一次见面,要商量用什么加密算法、交换密钥、验证身份——所有这些都在几毫秒内完成。

我画了一张流程图,帮你把TLS 1.2的完整握手过程看清楚:

TLS 1.2 完整握手流程图 TLS 1.2 完整握手流程 客户端 (Client) 服务端 (Server) 1. ClientHello TLS版本、密码套件、随机数 2. ServerHello + 证书 选定密码套件、服务端证书链 3. ServerHelloDone 4. 验证服务端证书 (信任链校验) 5. ClientKeyExchange 用服务端公钥加密的预主密钥 6. ChangeCipherSpec + Finished 7. ChangeCipherSpec + Finished 说明:TLS 1.3将握手从2-RTT优化为1-RTT,且证书加密传输,流程更简洁

上面这张图展示的是TLS 1.2的完整握手。我拆成几个关键步骤来讲:

  1. ClientHello — 客户端告诉服务端:我支持哪些TLS版本、哪些密码套件、以及一个随机数。这个随机数后面会用来生成会话密钥。
  2. ServerHello + 证书 — 服务端从客户端提供的列表里选一个密码套件,然后把自己的证书链发过去。注意,是证书链,不是单张证书。这个细节后面会反复讲。
  3. ServerHelloDone — 服务端说:我发完了,你继续。
  4. 客户端验证证书 — 这是咱们这门课的核心。客户端拿到证书后,要验证签名、有效期、域名匹配,还要沿着证书链一直追溯到根证书。如果验证失败,握手直接中断。
  5. ClientKeyExchange — 客户端生成一个预主密钥(pre-master secret),用服务端的公钥加密后发过去。只有持有对应私钥的服务端才能解密。
  6. ChangeCipherSpec + Finished — 双方各自通知对方:从现在开始,我要用协商好的密钥加密通信了。然后发一个Finished消息,里面包含之前所有握手消息的哈希值,用来确认握手没有被篡改。

小技巧:用Wireshark抓TLS握手包的时候,重点关注ClientHello里的密码套件列表和服务端返回的证书。我排查证书问题时,90%的情况在这两步就能定位到根因。

你可能会问:为什么TLS 1.3要把握手简化那么多?说白了,TLS 1.2的握手太啰嗦了。每次建立连接都要两轮往返,对于移动端或者高延迟网络来说,体验很差。TLS 1.3把ServerHello和证书一起发,还把密钥协商提前了,一轮往返就能搞定。