第3章 TLS/SSL协议:握手、验证与双向认证
做API网关层加密,TLS/SSL是躲不开的基本功。你可能觉得它就是个“加个https”,但实际集成时坑不少。这一章我们拆开揉碎讲。
3.1 TLS 1.3 握手——少了两轮,快了一截
我最早做网关加密时还在用TLS 1.2,那会儿握手要2-RTT才能拿到会话密钥。后来升级到1.3,减到1-RTT,甚至0-RTT(需谨慎)。
TLS 1.3握手核心步骤:
- ClientHello:客户端发送支持的密码套件、随机数、以及一个可通过DH或ECDH计算的密钥共享参数(Key Share)。
- ServerHello + 证书 + 签名:服务器选出密码套件,返回自己的密钥共享参数,同时带上证书链和数字签名。这一步就已经算出主密钥。
- 结束消息:双方派生出加密密钥,后面的应用数据直接加密传输。
小提示:TLS 1.3废弃了RSA密钥交换(因为不支持前向安全性),只保留ECDHE和DHE。我个人习惯用X25519曲线,性能好且安全。
对比1.2,1.3还移除了很多不安全的密码套件。GC错CBC模式、RC4这些老古董都被砍掉了。
注意:0-RTT模式下存在重放攻击风险。我曾经在一个支付网关项目里开了0-RTT,结果发现重放攻击测试部分失败。后来我们只在查询接口用0-RTT,写入接口老老实实走完整握手。
3.2 证书链验证——信任的传送带
公钥证书是TLS的信任基石。但客户端怎么知道服务器给的证书靠谱?靠证书链。
一个完整的证书链长这样:
- 叶子证书:由CA签发给你的网站(或API域)。
- 中间CA证书:用来签发叶子证书,避免根CA私钥被直接暴露。
- 根CA证书:预装在操作系统或浏览器里(比如IdenTrust、DigiCert的根)。
验证流程:
- 客户端从叶子证书开始,用上层证书的公钥验下层的签名。
- 一层层向上,直到自签名的根CA证书。
- 检查证书有效期、是否被吊销(CRL/OCSP),以及域名是否匹配。
我踩过的坑:有一次用户说“我的API访问报TLS错误”,我查了半天发现是他们用了自签名证书,但没有在客户端信任列表中加载根证书。其实证书链验证很简单:任何一个环节不信任,整个握手就断掉。
证书链验证还有一个细节:路径长度限制。根CA可以限制中间CA最多签发几级子CA。如果在证书里看到pathLenConstraint:0,意味着这个中间CA只能签发叶子证书,不能再签发下级CA。
3.3 双向认证(mTLS)——不只是验证服务端
常规TLS只验证服务器。mTLS要求客户端也提供证书,服务端验证客户端的身份。在微服务架构里,这东西特别有用。
握手流程多两步:
- 服务端在ServerHello之后,发送
CertificateRequest。 - 客户端收到后,发送自己的证书链,并做一次签名验证。
配置关键点:
| 环节 | 传统TLS | mTLS |
|---|---|---|
| 服务端证书 | 必须 | 必须 |
| 客户端证书 | 不要求 | 必须 |
| 验证方向 | 单向 | 双向 |
| 应用场景 | 公网用户访问 | 内部服务/设备通信 |
| 证书管理复杂 | 低 | 高(需给每个客户端签发) |
举个例子,Nginx启用mTLS:
server {
listen 443 ssl;
ssl_certificate /etc/certs/server.crt;
ssl_certificate_key /etc/certs/server.key;
ssl_client_certificate /etc/certs/ca.crt; # 用于验证客户端
ssl_verify_client on;
ssl_verify_depth 2;
注意 ssl_verify_client on 开启验证,ssl_verify_depth 控制证书链深度。我一般设为2或3,防止有中间CA层级太多导致验不过。
避坑提醒:我曾经在kubernetes里配mTLS时,没注意Ingress Controller的证书目录权限,结果Pod启动后找不到私钥。后来我统一用Secret挂载,权限设为600,就再没出过问题。
3.4 本章知识结构
3.5 实战建议与避坑
- 证书轮换:最好在证书到期前30天自动轮换,别等告警。我习惯用ACM或者cert-manager做自动化。
- 密码套件:只保留
TLS_AES_128_GCM_SHA256和TLS_AES_256_GCM_SHA384。CHACHA20_POLY1305在移动端确实有优势,但服务端用AES-GCM通常更快。 - 禁止弱协议:网关侧强制只开启TLS 1.2和1.3,最好直接砍掉TLS 1.0/1.1和SSL。
核心总结:TLS 1.3让握手更快、更安全;证书链验证是信任基石;mTLS让服务间通信更可信。这三样东西在网关层加密中缺一不可。