加密通信基础:TLS/SSL协议原理、握手过程、证书验证
说到加密通信,TLS/SSL是绕不开的基础设施。你可以把它想象成——给网络通信加了个密封的钢管。数据在进入钢管前加密,出去后解密,中间的人只能看到一堆乱码。
我刚开始做安全接入时,总觉得TLS很神秘。后来拆开看了几次,发现其实没那么复杂。说白了,就是三件事:身份认证、密钥协商、数据加密。
2.1 TLS/SSL的前世今生
SSL(Secure Sockets Layer)是网景公司在90年代推出的。后来IETF接手,改名叫TLS(Transport Layer Security)。现在用得最多的是TLS 1.2和TLS 1.3。
版本对照:SSL 3.0 → TLS 1.0 → TLS 1.1 → TLS 1.2 → TLS 1.3。TLS 1.3在2018年发布,握手速度明显提升。
我记得2014年有个项目,客户还在用SSL 3.0。当时POODLE漏洞刚爆出来,我硬是说服他们把整个集群升级到TLS 1.2。嗯,安全这种事,不能心疼迁移成本。
2.2 TLS握手过程——一次完整的加密对话
TLS握手,简单来说就是客户端和服务端互相确认身份、协商加密方法的过程。我用一个实际的抓包案例来解释。
假设你打开浏览器访问 https://example.com。以下是握手的核心步骤:
- ClientHello:客户端发一个打招呼包。里面带了它支持的TLS版本、密码套件列表、一个随机数。
- ServerHello:服务端回应,选一个双方都支持的TLS版本和密码套件,也发一个随机数。
- Certificate:服务端把自己的数字证书发给客户端。证书里包含公钥、颁发者等信息。
- ServerHelloDone:服务端说,我发完了,你继续。
- ClientKeyExchange:客户端生成一个预主密钥(Pre-Master Secret),用服务端的公钥加密后发过去。
- ChangeCipherSpec:双方切换加密模式。之后的数据就全是密文了。
- Finished:双方验证握手消息的完整性。验证通过,握手完成。
我在项目中遇到过一个问题:某个IoT设备握手一直失败。抓包一看,设备不支持服务端要求的密码套件。后来调整了服务端的密码策略,加了TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256才解决。说白了,就是双方得找到共同语言。
经验之谈:TLS 1.3把握手从2-RTT降到了1-RTT。如果服务端之前和客户端通信过,还能做到0-RTT。这在故障转移场景下特别有用——节点切换时,可以复用之前的会话。
2.3 证书验证——信任的源头
证书验证是TLS安全的核心。你想想看,如果任何人都能假装自己是银行网站,那加密就没意义了。
证书验证的流程是这样的:
- 客户端收到服务端的证书后,先检查证书链。从服务器证书开始,逐级向上验证,直到根证书。
- 检查证书是否过期,有没有被吊销(CRL或OCSP)。
- 验证证书的域名是否匹配访问的域名。
- 最后验证签名——用上一级证书的公钥解密签名,对比证书的哈希值。
我曾经踩过一个坑:一个内部系统用自签名证书,但客户端没有把CA证书加到信任库。结果所有TLS连接都报错,抓包显示certificate unknown错误。后来把CA证书部署到所有客户端的信任库里,才恢复正常。
注意:故障转移场景下,备用节点必须使用和主节点相同的证书,或者证书链能被客户端信任。否则切换后客户端会立刻报证书错误——这在生产环境是非常严重的故障。
2.4 密码套件——加密算法的组合
密码套件定义了TLS连接中使用的具体算法组合。常见的格式是:
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
│ │ │ │ │
│ │ │ │ └── 哈希算法(HMAC-SHA384)
│ │ │ └─────────── 对称加密算法(AES-256-GCM)
│ │ └───────────────────── 签名算法(RSA)
│ └────────────────────────── 密钥交换算法(ECDHE)
└───────────────────────────────── 协议(TLS)
我个人习惯在服务器上只启用强度够的密码套件。比如下面这个配置:
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_ecdh_curve prime256v1;
ssl_prefer_server_ciphers on;
为什么我这么选?因为ECDHE支持前向安全性——即使私钥泄露,之前的会话也无法被解密。这在故障转移中特别重要:如果某个节点的私钥意外泄露,之前的所有加密流量依然安全。你想想看,这是不是比单纯的RSA密钥交换靠谱多了?
2.5 会话恢复——提升性能的关键
完整的TLS握手很慢,尤其在高并发场景下。所以TLS支持会话恢复,有两种方式:
| 恢复方式 | 原理 | 适用场景 |
|---|---|---|
| Session ID | 服务端保存会话状态,客户端下次带上Session ID | 单节点,状态保存在内存里 |
| Session Ticket | 服务端加密会话状态,交给客户端保存 | 分布式集群,节点无需共享状态 |
Session Ticket在故障转移场景下非常实用。主节点故障后,备用节点只要持有相同的Ticket密钥,就能解密客户端带来的Ticket,直接恢复会话。
我建议在部署TLS接入层时,优先使用Session Ticket,并把Ticket密钥同步到所有节点。这样任何一个节点发生故障,客户端切到备用节点都无需重新握手。
2.6 本章知识体系
下面这张图我把TLS/SSL的核心逻辑串起来了。从协议分层到底层算法,再到握手流程和证书验证——一条线看明白。
这张图展示了TLS/SSL的核心脉络。从顶层的协议分层,到握手过程的7个步骤,再到证书验证和密码套件的选择,最后落到会话恢复——尤其是Session Ticket在故障转移中的实践。
嗯,把这些基础打牢了,后面讲故障转移机制时,你就能理解为什么TLS的某些特性恰恰是保障高可用通信的关键。