curl报91 No OCSP response received:cert-status与OCSP装订排查

普通curl请求成功,一加--cert-status就报91,错误写着No OCSP response received。这不等于证书过期,也不能直接认定证书已被吊销。本文用回环TLS实验拆开常规证书验证与OCSP装订检查,比较缺失、good和revoked响应,最后给出不会把诊断结果当验收的命令。

一、先看91检查的到底是什么

curl的--cert-status通过TLS证书状态请求扩展检查服务端装订的OCSP响应。官方手册明确:没有响应、响应无效或提示证书已吊销,都会导致验证失败;libcurl将相关失败列为CURLE_SSL_INVALIDCERTSTATUS,即91。

这里"没有响应"指握手没有拿到需要的装订材料,不是说网站没有HTTP正文。证书链受信、名称匹配和状态检查是不同条件。把CA文件换三遍,也不能让没有发送的OCSP响应突然出现。

二、把版本和普通请求留作对照

先保存curl版本及后端。当前官方手册列出的该选项支持后端为OpenSSL与GnuTLS,不能把本文输出推广到所有客户端。以下命令针对已准备好的本地测试服务:证书SAN包含localhost,ca.pem是经确认的测试CA,8443须替换为实际监听端口。

bash 复制代码
curl --version
openssl version
bash 复制代码
curl -q --noproxy '*' --cacert ca.pem \
  --connect-timeout 3 --max-time 8 \
  --fail --silent --show-error \
  --output baseline.txt --write-out '%{http_code}\n' \
  https://localhost:8443/

-q放在首个选项以跳过默认curlrc,避免隐藏配置改变对照;--noproxy仅用于这个回环实验,不是建议绕过生产网络策略。普通请求成功只建立一条基线,不能据此宣布OCSP策略已满足。正式排查要换成获授权的目标和可信材料,不安装测试CA到系统信任库。

三、用s_client观察装订,别把观察当裁判

下面固定连接地址、发送SNI,并显式校验名称和证书链。输出落盘后,在status.txt查看OCSP response及Cert Status字段,错误日志也要一起保留。命令在Bash中执行,诊断目录应只向必要用户开放。

bash 复制代码
openssl s_client -connect 127.0.0.1:8443 \
  -servername localhost -verify_hostname localhost \
  -verify_return_error -CAfile ca.pem -status \
  </dev/null > status.txt 2> status.err
rc=$?
[ "$rc" -eq 0 ] || exit "$rc"

关键边界是:-status用于请求并显示装订响应,不能把命令退出0直接解释为OCSP通过。本轮即使返回revoked,s_client也打印了对应状态并退出0;没有装订时同样可在常规证书验证通过后退出0。-verify_return_error不能自动补成curl --cert-status的语义。

别只搜索Verify return code: 0,那行与装订不是同一个判定对象。

四、隔离实验的正反例

本轮使用curl 7.61.1的OpenSSL后端、OpenSSL 1.1.1k FIPS命令行,在127.0.0.1随机端口运行TLS 1.2 s_server。临时CA签发localhost证书,并制作good与revoked的DER响应,通过-status_file装订;结束销毁证书、私钥与监听,未修改系统时间、信任库或生产配置。

测试条件 curl退出码 观察
不装订,普通请求 0 HTTP 200
不装订,加--cert-status 91 No OCSP response received
有效good装订,加状态检查 0 HTTP 200
revoked装订,加状态检查 91 报告吊销相关错误
good装订,换成无关CA 60 常规链信任仍然失败

失败请求的write-out为000,意思是未取得HTTP状态,不是服务器返回"000"。本轮只验证上述分支,没有把响应过期、代理、浏览器或所有TLS版本说成已实测。过期等无效响应的失败行为来自官方说明。

夹具还有个细节:本机旧curl最初在根直签且服务端仅发叶证书时报Error computing OCSP ID。为保证对照能定位状态检查,测试服务补发签发者后good通过。这个实验安排不等于生产应发送根证书;生产要按真实证书层级正确部署中间链。

五、按响应缺失、无效、吊销分别处理

没有装订,先确认请求落在哪个TLS终止点:CDN、负载均衡还是源站。检查该终止点是否支持并启用装订、证书签发体系是否提供适用的状态服务,以及它实际发送的证书和链。只在源站打开一个开关,不能证明边缘节点也已更新。

已有响应但验证失败,要核对响应对应的证书、签发者、签名与时间窗口;续期换证后仍缓存旧响应也是待排查方向,不能仅因文件"存在"就当正确。如果明确为revoked,应按证书事件处理流程更换材料并调查原因,而不是延长缓存或忽略错误。

若证书体系本来不提供适用装订,先确认监控要求是否成立,再由负责安全策略的人决定检测方式。删掉--cert-status只是撤销这项检查,不是修复装订;不要用-k关闭常规身份验证,也不要把改成绿灯当成问题解决。

六、用要求不变的请求验收

对于明确要求装订的目标,修复后仍须保留--cert-status。下面同时要求常规证书验证、状态检查、curl成功和测试接口HTTP 200;诊断文件不可写也应使脚本失败,而非悄悄丢证据。

bash 复制代码
umask 077
rc=0
curl -q --noproxy '*' --cacert ca.pem --cert-status \
  --connect-timeout 3 --max-time 8 \
  --fail --silent --show-error \
  --output body.txt --write-out '%{http_code}' \
  https://localhost:8443/ > probe.status 2> probe.err || rc=$?
[ "$rc" -eq 0 ] || exit "$rc"
[ "$(<probe.status)" = 200 ] || exit 1

200是本文测试接口契约,不是所有业务的唯一成功状态。--fail处理HTTP错误;实际应用还应核对必要的业务响应。本轮重放四段最终代码,缺失与revoked装订都不能通过最后的包装器,错误日志目录不存在也会阻止通过。

七、最后按清单交付

验收清单:记录版本与TLS后端;确认授权目标和TLS终止点;普通请求与状态检查使用同一身份和可信CA;区分无装订、无效与revoked;保留完整退出码和日志;按不变的安全要求重复探测。多节点场景逐个覆盖已知目标,不能拿一次成功代表所有入口。

本文验证的是隔离TLS 1.2测试,不是生产证书吊销状态报告。离线DER文件也不是可以长期复制使用的生产响应。真正要交付的是"检查了什么、为什么通过",而不只是一行绿色成功。

八、参考资料

相关推荐
Lsetea4 小时前
OpenSSL报self-signed certificate in certificate chain:error 19与信任根排查
https·ssl证书·openssl·curl·证书链
zxanz11 天前
网站为什么需要 SSL 证书来实现 https?
https
Lsetea1 天前
curl报58 unable to set private key file:客户端证书与私钥加载排查
运维·https·ssl证书·openssl·curl
Lsetea1 天前
OpenSSL报certificate is not yet valid:error 9与notBefore时间排查
linux·运维·https·ssl证书·openssl
2501_915909061 天前
iOS应用从开发到上架App Store的完整发布流程与步骤指南
android·ios·小程序·https·uni-app·webview
Smoothcloud润云2 天前
GPU服务器租用实例DNS与HTTPS下载排障实战
大数据·运维·服务器·人工智能·https·gpu算力
神一样的老师2 天前
WS63 访问 HTTPS 握手失败(-0x7780)根治
数据库·网络协议·https
Lsetea3 天前
curl用IP测试HTTPS报证书不匹配:--resolve与Host头别混用
linux·https·ssl证书·openssl·curl