一个CDN客户反馈,开启HTTPS后页面首屏加载慢了将近300毫秒,排查发现时间花在了证书吊销状态的在线查询上。浏览器每次建立SSL连接时都会去CA服务器查证书是否被吊销,这个往返就吃掉了几百毫秒。
吊销检查的两种老办法和各自的问题
证书吊销列表(CRL)是最早的方案。CA定期发布一个被吊销证书的列表,浏览器下载这个列表后检查本地。问题在于:CRL文件会越来越大,下载耗时;而且更新有延迟,一张证书被吊销后可能要几个小时甚至几天才出现在列表里。
在线证书状态协议(OCSP)是替代方案。浏览器实时向CA的OCSP服务器查询某张证书的吊销状态,响应快。但新问题来了:浏览器每次HTTPS连接都要发一次OCSP请求,如果CA的OCSP服务器响应慢或者网络不通,浏览器要么等待要么直接报错。
更麻烦的是隐私问题。CA的OCSP服务器知道哪些用户在访问哪些网站,这些请求数据本身就有泄露风险。
OCSP Stapling是怎么解决这个问题的
OCSP Stapling的思路很直接:不让浏览器去查,让服务器代替浏览器去查,然后把结果“钉“在SSL握手阶段一起发给浏览器。
具体流程是:服务器定期(通常每24-48小时)向CA的OCSP服务器查询自己的证书吊销状态,拿到一个带签名的响应缓存到本地。浏览器发起SSL连接时,服务器在握手包里直接带上这个缓存响应。浏览器验证签名通过就跳过在线查询,省掉一个网络往返。
效果立竿见影:SSL握手时间减少100-300毫秒,浏览器不再依赖CA服务器的可用性,隐私泄露问题也一并解决。
Nginx和Apache的配置方法
Nginx配置:在server段加上三行——ssl_stapling on;、ssl_stapling_verify on;、resolver 8.8.8.8 valid=300s;。同时确保证书链完整,中间证书必须配置,否则Stapling会静默失败。
Apache配置:SSLUseStapling On,并在全局配置中设置SSLStaplingCache shmcb:/var/run/ocsp(128000)来指定缓存路径和大小。
配置完成后用openssl s_client -connect 你的域名:443 -status验证,输出中出现“OCSP Response Status: successful“就说明Stapling已经生效。
如果显示“no response“,检查三个地方:证书链是否完整、服务器能否访问CA的OCSP接口、CA是否支持OCSP Stapling(少数小CA不支持)。
这个配置投入成本几乎为零,但对用户体验的改善是实打实的。安全检查不该以牺牲速度为代价。