OCSP Stapling 工作原理

说起 OCSP Stapling,其实它要解决一个很实际的问题——验证证书时,客户端自己去 OCSP 响应器查状态,效率太低了。我早年做 HTTPS 优化时就发现,光 OCSP 查询这一项,就能让 TLS 握手时间翻倍。后来才搞明白,Stapling 就是把 OCSP 响应直接“钉”在证书上,交给服务器代劳。

TLS 握手中的角色转换

正常的 TLS 握手流程,客户端收到服务端证书后,自己去找 OCSP 响应器问这张证书有没有被吊销。这有几个明显的问题:

  • 额外开销:客户端得多发一次 HTTP 请求,尤其移动端网络差,影响很大。
  • 隐私泄露:OCSP 响应器知道你访问了哪个站点。
  • 单点故障:OCSP 响应器挂了,浏览器可能直接拒绝连接,或者干脆忽略验证。

Stapling 的思路正好反过来——证书状态的查询工作,由服务端来做。服务端定期从 CA 拉取 OCSP 响应,缓存在本地。等到客户端发起 TLS 握手时,服务端直接在握手过程中把这个响应“塞”给客户端。

我个人习惯把这个过程理解为:「服务端帮你去柜台盖了个章,然后把盖章的结果当场递给你看」。你不需要自己跑一趟,既省时间又防作伪。

Certificate Status Request 扩展

这个机制能工作,全靠 TLS 协议里的一个扩展——status_request(也叫 Certificate Status Request)。它定义在 RFC 6066 里。流程如下:

  1. 客户端声明:在 ClientHello 消息中带上 status_request 扩展,表示「我支持 OCSP Stapling,请直接把响应给我」。
  2. 服务端响应:服务端看到这个扩展后,在 Certificate 消息之后,直接捎带一个 CertificateStatus 消息,里面就是缓存的 OCSP 响应。
  3. 客户端验证:客户端收到后,校验这个响应的签名是否来自 CA,以及响应中的序列号是否跟证书一致。
知识点:其实不是所有客户端都支持这个扩展。我当初排一个 Nginx 配置问题时发现,某些旧版 curl 或者 OpenSSL 版本默认不发送 status_request,导致 Stapling 根本没生效。检查一下客户端支持情况,往往比调服务器配置更重要。

服务器如何缓存 OCSP 响应

服务端从 CA 的 OCSP 响应器拉取响应后,不会每次都重新请求。它会缓存一段时间,这个时间由 OCSP 响应里的 nextUpdate 字段控制。一般来说,CA 颁发的 OCSP 响应有效期是 4 到 7 天。但实际情况要复杂很多:

  • 响应有效期太短:有些 CA 只给 1 小时有效期,服务端就得频繁拉取,压力不小。
  • 响应有效期太长:如果证书被紧急吊销,客户端可能在有效期内拿到一个「未吊销」的旧响应。

我曾经在线上遇到过一个问题——某个 CA 的 OCSP 响应有效期是 7 天,但证书第二天就被吊销了。结果那 7 天内,所有使用 Stapling 的客户端都认为证书正常。嗯,这里要注意,Stapling 只是一个优化手段,它不能替代 CRL 或者实时 OCSP 查询。

合规检查的关键:检查 OCSP 响应的有效期是否太短或太长。一般来说,24-72 小时是比较合理的范围。如果超过 7 天,应该标记为高风险。

一张图看懂流程

下面这张图我画了个简化流程,把 Stapling 和传统 OCSP 的核心区别放在一起对比。

OCSP Stapling 与标准 OCSP 流程对比 标准 OCSP 流程 客户端 服务端 OCSP 响应器 TLS 握手 客户端自己查询状态 OCSP Stapling 流程 客户端 服务端 OCSP 响应器 TLS 握手 服务端定期拉取 服务端本地缓存 OCSP 响应
实用建议:你可以在 Nginx 或 Apache 配置里打开 ssl_stapling 和 ssl_stapling_verify。然后用 OpenSSL 的 s_client 命令加 -status 参数检查一下,看能不能拿到 OCSP 响应。我记得有人问过我「为什么开启后没效果」,其实就是忘了配 ssl_trusted_certificate 链,导致客户端无法验证。

合规检查的落脚点

理解了工作原理后,你会发现合规检查其实就在以下几个点上:

检查项 说明 常见问题
扩展声明 客户端是否发送 status_request 扩展 某些旧版浏览器/库不发
响应缓存 服务端是否正确缓存并更新 OCSP 响应 缓存过期、更新策略错误
响应验证 客户端是否校验 Stapled 响应的签名和序列号 跳过验证等同虚设
错误处理 服务端拿不到 OCSP 响应时怎么处理 直接断开连接或降级为普通 OCSP

说白了,Stapling 的核心就是让服务端分担客户端的验证负担。但如果你配置不到位,这个「分担」反而可能引入新的合规风险。我个人习惯在刚配置完时,用抓包工具看一眼 TLS 握手阶段有没有 CertificateStatus 消息,有就对了,没有就继续调。