如何利用Nginx ssl_stapling优化HTTPS证书校验,减少握手延迟?
- 内容介绍
- 文章标签
- 相关推荐
本文共计990个文字,预计阅读时间需要4分钟。
运行以下命令可以查看证书内容:
若无输出或显示 URI: http:// 后为空、域名不可达(如 http://ocsp.example.com 但 DNS 解析失败),stapling 就不会发起请求
- Let’s Encrypt 证书通常含
http://ocsp.int-x3.letsencrypt.org/,可用 - 自签名或私有 CA 证书默认不带 OCSP URI,需重签或手动注入(用
openssl ca -extensions v3_ocsp等) - 中间证书缺失也会导致 AIA 解析失败——
ssl_certificate必须是fullchain.pem(服务器证书 + 中间证书),不能只放域名证书
resolver 必须显式配置且能连通 OCSP 域名
Nginx 完全忽略系统/etc/resolv.conf,不配 resolver 就等于没 DNS,OCSP 查询直接超时降级。
在 http 或 server 块中加:
resolver 1.1.1.1 8.8.8.8 valid=300s; resolver_timeout 5s;
valid=300s 避免频繁解析;resolver_timeout 5s 防止一次 DNS 卡住整个握手
- 若 OCSP 地址是内网域名(如
ocsp.internal-ca.local),resolver 必须指向能解析它的 DNS(如内网 CoreDNS),公网 DNS(如 1.1.1.1)会失败 - 测试连通性:用
dig @1.1.1.1 ocsp.int-x3.letsencrypt.org或curl -v http://ocsp.int-x3.letsencrypt.org确认 DNS 和 HTTP 层都通 - 多个 resolver 可并列写,Nginx 会轮询,防单点故障
ssl_stapling_verify on 依赖 ssl_trusted_certificate 正确拼接
开启校验后,Nginx 会用ssl_trusted_certificate 文件验证 OCSP 响应签名。文件错一个字节,stapling 就被禁用,日志里只报 certificate verify failed。
该文件不是 ssl_certificate,而是专用于 OCSP 验证的 CA 信任链:
- 内容必须按顺序拼接:**中间证书在前,根证书在后**(例如 Let’s Encrypt 的
chain.pem) - 不能包含服务器证书本身,也不能混入无关 CA(如系统 ca-certificates)
- 验证方式:
openssl ocsp -issuer intermediate.crt -cert server.crt -url http://ocsp.int-x3.letsencrypt.org/ -CAfile /path/to/ssl_trusted_certificate.pem -text,输出含CertStatus: good才算有效 - 路径权限要放开:
chown www-data:www-data /path/to/trust.pem,否则 Nginx worker 进程读不了
内网私有 CA 必须放弃自动 stapling,改用文件缓存
私有 OCSP 响应器往往没有公网 DNS、受防火墙限制,Nginx 内置的 resolver + 自动拉取机制基本不可用。可靠做法是:定期用 openssl ocsp 主动获取响应,写入本地文件,再由 Nginx 直接加载:
openssl ocsp -issuer ca.crt -cert server.crt -url http://ocsp.internal-ca.local \ -respout /var/lib/nginx/ocsp/server.ocsp -text
然后配置:
ssl_stapling_file /var/lib/nginx/ocsp/server.ocsp; ssl_stapling on; ssl_stapling_verify on;
-
ssl_stapling_file指向的是二进制 OCSP 响应(不是文本),-respout参数生成的就是它 - 用 cron 定期更新(如每 4 小时),但注意检查 OCSP 响应里的
nextUpdate时间,别缓存过期响应 - 此时
resolver和ssl_trusted_certificate仍需保留——前者虽不用来查 OCSP 域名,但可能被其他模块(如 proxy_pass)复用;后者仍用于验证本地缓存响应的签名
openssl s_client -connect example.com:443 -status -servername example.com 2>&1 | grep -A2 "OCSP response"。看到 OCSP Response Status: successful (0x0) 和 CertStatus: good 才算真正落地。很多线上环境看似配置完整,但漏掉了中间证书拼接顺序或 resolver 权限,结果 stapling 始终处于“假启用”状态。本文共计990个文字,预计阅读时间需要4分钟。
运行以下命令可以查看证书内容:
若无输出或显示 URI: http:// 后为空、域名不可达(如 http://ocsp.example.com 但 DNS 解析失败),stapling 就不会发起请求
- Let’s Encrypt 证书通常含
http://ocsp.int-x3.letsencrypt.org/,可用 - 自签名或私有 CA 证书默认不带 OCSP URI,需重签或手动注入(用
openssl ca -extensions v3_ocsp等) - 中间证书缺失也会导致 AIA 解析失败——
ssl_certificate必须是fullchain.pem(服务器证书 + 中间证书),不能只放域名证书
resolver 必须显式配置且能连通 OCSP 域名
Nginx 完全忽略系统/etc/resolv.conf,不配 resolver 就等于没 DNS,OCSP 查询直接超时降级。
在 http 或 server 块中加:
resolver 1.1.1.1 8.8.8.8 valid=300s; resolver_timeout 5s;
valid=300s 避免频繁解析;resolver_timeout 5s 防止一次 DNS 卡住整个握手
- 若 OCSP 地址是内网域名(如
ocsp.internal-ca.local),resolver 必须指向能解析它的 DNS(如内网 CoreDNS),公网 DNS(如 1.1.1.1)会失败 - 测试连通性:用
dig @1.1.1.1 ocsp.int-x3.letsencrypt.org或curl -v http://ocsp.int-x3.letsencrypt.org确认 DNS 和 HTTP 层都通 - 多个 resolver 可并列写,Nginx 会轮询,防单点故障
ssl_stapling_verify on 依赖 ssl_trusted_certificate 正确拼接
开启校验后,Nginx 会用ssl_trusted_certificate 文件验证 OCSP 响应签名。文件错一个字节,stapling 就被禁用,日志里只报 certificate verify failed。
该文件不是 ssl_certificate,而是专用于 OCSP 验证的 CA 信任链:
- 内容必须按顺序拼接:**中间证书在前,根证书在后**(例如 Let’s Encrypt 的
chain.pem) - 不能包含服务器证书本身,也不能混入无关 CA(如系统 ca-certificates)
- 验证方式:
openssl ocsp -issuer intermediate.crt -cert server.crt -url http://ocsp.int-x3.letsencrypt.org/ -CAfile /path/to/ssl_trusted_certificate.pem -text,输出含CertStatus: good才算有效 - 路径权限要放开:
chown www-data:www-data /path/to/trust.pem,否则 Nginx worker 进程读不了
内网私有 CA 必须放弃自动 stapling,改用文件缓存
私有 OCSP 响应器往往没有公网 DNS、受防火墙限制,Nginx 内置的 resolver + 自动拉取机制基本不可用。可靠做法是:定期用 openssl ocsp 主动获取响应,写入本地文件,再由 Nginx 直接加载:
openssl ocsp -issuer ca.crt -cert server.crt -url http://ocsp.internal-ca.local \ -respout /var/lib/nginx/ocsp/server.ocsp -text
然后配置:
ssl_stapling_file /var/lib/nginx/ocsp/server.ocsp; ssl_stapling on; ssl_stapling_verify on;
-
ssl_stapling_file指向的是二进制 OCSP 响应(不是文本),-respout参数生成的就是它 - 用 cron 定期更新(如每 4 小时),但注意检查 OCSP 响应里的
nextUpdate时间,别缓存过期响应 - 此时
resolver和ssl_trusted_certificate仍需保留——前者虽不用来查 OCSP 域名,但可能被其他模块(如 proxy_pass)复用;后者仍用于验证本地缓存响应的签名
openssl s_client -connect example.com:443 -status -servername example.com 2>&1 | grep -A2 "OCSP response"。看到 OCSP Response Status: successful (0x0) 和 CertStatus: good 才算真正落地。很多线上环境看似配置完整,但漏掉了中间证书拼接顺序或 resolver 权限,结果 stapling 始终处于“假启用”状态。
