nginx 不主动管理 ocsp 响应生命周期,需外部脚本按域名隔离执行:提取证书与中间链→解析 ocsp uri→拉取并三重校验(签名、状态、有效期)→原子替换 .resp 文件→nginx 自动加载;须 cron 分时调度、权限匹配、per-server 配置。

Nginx 本身不主动管理 OCSP 响应的生命周期,要实现“定期检查并更新各站点 OCSP 状态”,必须靠外部脚本驱动:探测证书有效性 → 拉取新 OCSP 响应 → 校验通过后原子替换 → 触发 Nginx 加载。整个过程需按域名隔离、失败不中断、响应文件严格校验。
每个域名独立维护 OCSP 响应文件
Nginx 的 ssl_stapling_file 是 per-server 的,不同域名必须用不同 .resp 文件,不能共用。脚本需遍历所有启用 HTTPS 的 server 块所指向的证书路径(如 /etc/letsencrypt/live/example.com/fullchain.pem),为每个域名单独生成、校验、部署响应文件。
- 先提取域名证书和中间证书(
fullchain.pem已含两者,但需拆分为cert.pem+ca.cer才能被openssl ocsp正确识别) - 从证书中读取
OCSP URI(openssl x509 -in cert.pem -noout -text | grep OCSP),避免硬编码 URL - 使用
openssl ocsp -issuer ca.cer -cert cert.pem -url $OCSP_URL -respout domain.ocsp.resp生成 DER 格式响应
脚本必须做三重校验才允许替换
直接覆盖旧 .resp 文件风险极高。更新前务必确认新响应:
- 签名可被
ssl_trusted_certificate中的 CA 验证(openssl ocsp -verify_other ca.cer -trust_other -no_nonce -respin domain.ocsp.resp -text) - 状态为
response is good(grep -q ": good" output) - 有效期覆盖未来至少 24 小时(
openssl ocsp -respin domain.ocsp.resp -text | grep "This Update\|Next Update")
任一失败,保留原文件,记录错误到日志,不触发 reload。
更新后无需手动 reload,Nginx 自动生效
只要 ssl_stapling_file 指向的文件被原子替换(例如 mv domain.ocsp.resp.new domain.ocsp.resp),Nginx 在下一次 TLS 握手时会自动加载新内容——它监听文件 mtime 变更,无需 nginx -s reload。
- 确保该文件权限与 Nginx worker 进程一致(通常
nginx:nginx或www-data:www-data) - 文件路径需在
ssl_stapling_file中显式声明,且位于server块内(不能只写在http块)
用 cron 统一调度,按域名分片执行
将脚本设计为接受域名参数:/usr/local/bin/update-ocsp.sh example.com,再在系统 crontab 中为每个关键域名单独排期(避免单点失败影响全部):
# 每天凌晨 3:17 更新 example.com 17 3 * * * /usr/local/bin/update-ocsp.sh example.com >> /var/log/ocsp-update-example.log 2>&1 # 每天凌晨 3:23 更新 api.example.com 23 3 * * * /usr/local/bin/update-ocsp.sh api.example.com >> /var/log/ocsp-update-api.log 2>&1
时间错开可降低 OCSP 查询对上游 CA 服务的压力,也便于定位单域名异常。
不复杂但容易忽略:OCSP 响应不是“生成即有效”,它依赖完整信任链验证和时间窗口匹配。脚本里少一个 openssl ocsp -verify_other,就可能把伪造或过期响应当真用。











