第一章|TLS协议基础:版本历史、握手过程与证书体系
大家好,我是这门课的主讲。先问个问题:你平时调试 HTTPS 接口时,是不是直接跳过协议细节,只关心证书报错?我以前也这么干。直到有一次线上双向认证频繁断开,排查了三天才发现是 TLS 版本不匹配——那个坑我到现在还记得。
这一章我们就把 TLS 协议基础打牢。别担心,不会照搬 RFC。我会结合我踩过的坑、调过的包,帮你把三个核心知识点吃透:版本演进、握手的舞台剧、证书体系怎么兜底。
1.1 TLS 版本历史:从 SSL 到 TLS 1.3
TLS 的前身是 Netscape 搞出来的 SSL,版本号一路从 1.0、2.0、3.0 升级到 1999 年改名为 TLS 1.0。说白了,TLS 1.0 就是 SSL 3.0 的小修小补。但 2014 年爆出 POODLE 漏洞后,SSL 3.0 被彻底抛弃。
下面是主流版本的关键差异——我整理成表格,方便你对比:
| 协议版本 | 推出年份 | 主要改进 | 当前状态 |
|---|---|---|---|
| SSL 3.0 | 1996 | 首个广泛部署的加密层 | 已禁用(POODLE 漏洞) |
| TLS 1.0 | 1999 | 更安全的 HMAC、不同加密套件 | 已弃用(BEAST 攻击) |
| TLS 1.1 | 2006 | 增加 CBC 防护、隐式 IV | 已弃用 |
| TLS 1.2 | 2008 | GCM/CCM 模式、SHA-256、AEAD | 仍广泛使用(推荐) |
| TLS 1.3 | 2018 | 精简握手、移除不安全算法、0-RTT | 强烈推荐(最新) |
我个人习惯:新项目直接锁死 TLS 1.2 和 1.3,禁用 1.1 及以下。为什么?我在一次安全扫描中发现客户的服务还支持 TLS 1.0,结果被扫出一个弱加密套件……改配置只用了一分钟,但修复报告折腾了好几天。
版本演进的本质:握手速度越来越快,安全边界越来越窄。TLS 1.3 把握手从 2-RTT 砍到 1-RTT(甚至 0-RTT),同时砍掉了那些容易出问题的算法(比如 RC4、CBC 模式)。
1.2 握手过程:一场丝滑的“协议谈判”
TLS 握手说复杂也复杂,说简单也简单。你想象一下:客户端和服务端第一次见面,需要依次确定三件事——用什么版本、用什么加密套件、交换密钥。握手就是这三步的一个加密版流程。
我直接画了一张 TLS 1.3 的握手流程图,节点和箭头都标清楚了。建议你边看边对照:
看看这张图,你会发现 TSL 1.3 把原来的“两次往返”砍成了一次。客户端发 ClientHello 的时候,就直接把密钥分享的参数也带上了。服务端回复 ServerHello 时,也顺带把自己的密钥分享和证书一起发过来。这样一来,双方只需要一次网络往返就能算出手握密钥。
握手过程里有一个关键点:证书验证。服务端发的证书必须是可信的,否则客户端会直接中断握手。我曾经遇到过一个案例:线上业务突然中断,排查发现是服务端证书过期了,但监控只报了“握手失败”,根本没有具体原因。嗯,从那以后我强制加了证书过期告警。
1.3 证书体系概述:信任链和双向认证
证书是 TLS 的身份证。它解决的核心问题:你怎么知道对方就是你想通信的那个人?
证书体系围绕三个角色建立:
- CA(证书颁发机构) —— 权威的第三方,负责给服务器/客户端发证。全球有几十个根 CA,比如 DigiCert、GlobalSign、Let's Encrypt。
- 服务器/客户端证书 —— 包含公钥、组织信息、有效期,由 CA 签名。
- 信任链 —— 根证书 → 中间证书 → 终端证书。操作系统和浏览器天生信任根证书,逐级验证签名。
在双向认证中,服务器也要验证客户端的证书。说白了,单向认证只查身份证(服务器证书),双向认证要双方互查身份证。
我整理了一个对比表,方便你快速记住差异:
| 特性 | 单向认证(HTTPS 网页) | 双向认证(mTLS) |
|---|---|---|
| 服务器是否发证书 | 是 | 是 |
| 客户端是否发证书 | 否 | 是 |
| 验证方向 | 客户端验证服务器 | 双方互相验证 |
| 典型场景 | 浏览器访问网站 | API 接口、微服务间调用 |
| 证书管理复杂度 | 低 | 高(客户端需要单独签发) |
我个人习惯:在内部系统通信中尽量启用双向认证。为什么?有一次我们公司的网关被扫出未授权的非法请求,就是因为只做了 IP 白名单和 认证,而 被泄漏了。换成 mTLS 后,即使 泄漏,没有客户端证书的请求直接被 TLS 层拒绝,安全等级立马提升一个量级。
证书还有一个关键概念:证书链的深度。你想想看,根证书如果泄露了,整个信任体系都完蛋。所以实际 CA 通常签发“中间证书”,只有中间证书被用来签终端证书。根证书则锁在硬件加密机里,几乎不上网。
openssl s_client -connect example.com:443 -showcerts输出里会列出每一级证书。我曾经用这个命令抓到一个中间证书不完整的部署,服务端只发了自己的服务器证书,但没有发中间证书。结果很多老客户端不信任,直接抛出错误。
证书格式也容易混淆。PEM(Base64 编码)和 DER(二进制编码)是最常见的。我建议统一用 PEM 格式,因为文本可读性好,而且几乎所有的服务器都支持。至于 PFX/P12 通常会在生成双向认证客户端证书时用到,后面章节会单独讲解。