验证与连接测试

OpenSSL 检查证书吊销:OCSP 与 CRL 命令

作者: · 最后核实 实测 macOS · OpenSSL 3.6.1

证书吊销用来告诉客户端:这张证书虽然没到期,但已经不该再被信任。吊销信息有两种发布方式:OCSP(按证书在线查询)和 CRL(CA 签名的吊销序列号列表)。下面的 OpenSSL 3.x 命令用来找出证书里的吊销地址、查询它们,并用它们验证证书链。注意 Let's Encrypt 已在 2025 年停用 OCSP,它签发的证书只能通过 CRL 检查,背景见 OCSP 与 CRL 原理。

找出 OCSP 地址和 CRL 分发点

OCSP 地址在 AIA(颁发机构信息访问)扩展里,CRL 地址在 CRL 分发点扩展里。

openssl x509 -in cert.pem -noout -ocsp_uri
openssl x509 -in cert.pem -noout -ext authorityInfoAccess,crlDistributionPoints
Authority Information Access: 
    CA Issuers - URI:http://ye2.i.lencr.org/
X509v3 CRL Distribution Points: 
    Full Name:
      URI:http://ye2.c.lencr.org/51.crl

这是 2026 年 11 月检查的一张 Let's Encrypt 证书:-ocsp_uri 没有任何输出,AIA 里只剩 CA Issuers 地址。CRL 地址末尾是分片编号,因为 Let's Encrypt 把 CRL 拆成了很多小文件。仍在提供 OCSP 的 CA 签发的证书,-ocsp_uri 会输出类似 http://ocsp.example.net 的地址。

向 OCSP 服务器查询

openssl ocsp 需要签发者证书、待查证书和 OCSP 地址三样东西。

openssl ocsp -issuer intermediate.pem -cert cert.pem -url http://ocsp.example.net
WARNING: no nonce in response
Response verify OK
cert.pem: good
    This Update: Nov  8 22:09:00 2026 GMT
    Next Update: Nov 15 21:09:00 2026 GMT

状态有 good、revoked、unknown 三种。Response verify OK 表示响应签名能链到受信任的根;默认信任库里缺这个根时加 -CAfile root.pem,只想看一眼可以加 -noverify。公网 OCSP 服务大多返回预先签好的响应,不回显随机数,所以会有那条警告,加 -no_nonce 可以去掉。intermediate.pem 可以用 -showcerts 从服务器取,也可以从 CA Issuers 地址下载(见验证证书链)。

查看完整的 OCSP 响应

-resp_text 会打印响应者 ID、证书 ID 以及响应的有效时间窗口。

openssl ocsp -issuer intermediate.pem -cert cert.pem -url http://ocsp.example.net -resp_text -no_nonce
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: 6A4E50BF98689D5B7B2075D45901794866923206
    Produced At: Nov  8 22:25:24 2026 GMT
    Responses:
    Certificate ID:
      Hash Algorithm: sha1
      Issuer Name Hash: D613075FB6DEA11BDF0182D397E1D37C6E925509
      Issuer Key Hash: 6A4E50BF98689D5B7B2075D45901794866923206
      Serial Number: 0F07FCB7C21FB7667C1BFD9496F28B4C
    Cert Status: good
    This Update: Nov  8 22:09:00 2026 GMT
    Next Update: Nov 15 21:09:00 2026 GMT

证书 ID 由签发者名称哈希、签发者公钥哈希和序列号组成,所以签发者证书必不可少。这里的 SHA-1 只是用作标识,不是签名算法。响应只在 This Update 到 Next Update 之间有效,服务器装订了过期响应,严格的客户端会报错。

查看服务器装订的 OCSP 响应

s_client -status 请求 OCSP 装订,服务器返回了就打印出来。

openssl s_client -connect www.example.com:443 -servername www.example.com -status < /dev/null 2>/dev/null \
  | sed -n '/OCSP response/,/Next Update/p'
OCSP responses: number of responses: 1
======================================
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    ...
    Cert Status: good
    This Update: Nov  9 04:50:45 2026 GMT
    Next Update: Nov 16 04:50:45 2026 GMT

显示 OCSP responses: no responses sent 表示没有装订,证书没有 OCSP 地址时本来就该如此。证书有 OCSP 地址时,Nginx 是在收到请求后才去取响应的,重载后的第一次请求常常没有装订,多跑一次即可;另外 Nginx 装订需要配置 resolver,国内服务器可以用 223.5.5.5 或 119.29.29.29 这类公共 DNS。3.x 之前的版本显示的是单数形式 OCSP response: no response sent。

检查证书是否要求必须装订(Must-Staple)

带有 status_request 的 TLS Feature 扩展,表示这张证书要求服务器必须装订 OCSP 响应。

openssl x509 -in cert.pem -noout -ext tlsfeature
TLS Feature: 
    status_request

没有输出说明不带这个扩展,绝大多数证书都是如此。执行 Must-Staple 的客户端(Firefox 多年来一直如此)在收不到装订响应时会直接拒绝连接。Let's Encrypt 在 2025 年 5 月 7 日停止写入 OCSP 地址的同时,也不再签发 Must-Staple 证书,老配置里如果还有 --must-staple 参数要删掉。参见 Must-Staple。

保存 OCSP 响应并从文件装订

-respout 把 DER 格式的响应写成文件,服务器访问不到 OCSP 服务时可以用它装订。

openssl ocsp -issuer intermediate.pem -cert cert.pem -url http://ocsp.example.net \
  -no_nonce -respout cert.ocsp
openssl s_server -accept 8443 -cert cert.pem -key key.pem -cert_chain intermediate.pem \
  -status_file cert.ocsp -www
Response verify OK
cert.pem: good
    This Update: Nov  9 18:19:28 2026 GMT

用 openssl s_client -connect 127.0.0.1:8443 -status 测试效果。Nginx 的 ssl_stapling_file、HAProxy 的 .ocsp 文件都用这种 DER 格式。服务器所在网络访问境外 OCSP 服务不稳定时,这种“离线装订”很实用,但要用 cron 在 Next Update 之前及时刷新。

下载并查看 CRL

CRL 通常以 DER 格式通过 HTTP 提供,用 openssl crl -inform DER 读取。

curl -s -o ca.crl http://ye2.c.lencr.org/51.crl
openssl crl -inform DER -in ca.crl -noout -issuer -lastupdate -nextupdate -crlnumber
openssl crl -inform DER -in ca.crl -noout -text | head -25
issuer=C=US, O=Let's Encrypt, CN=YE2
lastUpdate=Nov  9 17:52:09 2026 GMT
nextUpdate=Nov 18 17:52:08 2026 GMT
crlNumber=0x18E671E4DCCF25A0
Certificate Revocation List (CRL):
    ...
        X509v3 Issuing Distribution Point: critical
            Full Name:
              URI:http://ye2.c.lencr.org/51.crl
            Only User Certificates
Revoked Certificates:
    Serial Number: 05E7C117F64B64BC83F3691B78C8F454F1B2
        Revocation Date: Sep 24 17:49:02 2026 GMT
    Serial Number: 06D1E637E94367185DAF628054DAD4CED532
        Revocation Date: Aug 17 16:24:19 2026 GMT
        CRL entry extensions:
            X509v3 CRL Reason Code: 
                Key Compromise

这个分片约 100 KB,包含 2345 条记录。Issuing Distribution Point 扩展表明它是只覆盖终端证书的分片 CRL。如果 openssl crl 报解码错误,说明文件本来就是 PEM,去掉 -inform DER 即可。

在 CRL 里查找某张证书

取出证书的序列号,到解码后的 CRL 里搜索。

SERIAL=$(openssl x509 -in cert.pem -noout -serial | cut -d= -f2)
echo "$SERIAL"
openssl crl -inform DER -in ca.crl -noout -text | grep -c "$SERIAL"
05688C92AD512A3678DB6355831A0BFBBD32
0

结果为 0 表示这张证书不在该 CRL 上。两条命令输出的都是不带冒号的大写十六进制,直接 grep 就行。一定要下载证书自己 CRL 分发点里写的那个文件,分片 CRL 查错分片等于没查。

验证 CRL 的签名

openssl crl -CAfile 检查 CRL 是否由指定的签发者签名。

openssl crl -inform DER -in ca.crl -CAfile intermediate.pem -noout
verify OK

显示 verify failure 说明 CRL 是另一把密钥签的,比如换代后的另一张中间证书。通过 HTTP 下载的 CRL 用之前一定先验签:它的可信度来自签名,而不是传输通道。

带 CRL 检查验证证书链

openssl verify -crl_check 用 CRL 检查服务器证书,-crl_download 则按证书里的地址自动下载 CRL。

openssl verify -crl_check -CRLfile ca.crl -untrusted chain.pem cert.pem
openssl verify -crl_check -crl_download -untrusted chain.pem cert.pem
cert.pem: OK
cert.pem: OK

已吊销的证书会报 error 23 at 0 depth lookup: certificate revoked。-crl_check_all 还要求中间证书也有 CRL,缺了就报 error 3 at 1 depth lookup: unable to get certificate CRL。OpenSSL 3.x 的 -CRLfile 能直接读 PEM 和 DER。浏览器里吊销证书显示为 NET::ERR_CERT_REVOKED。

为私有 CA 运行测试用 OCSP 服务

openssl ocsp -index 能基于 openssl ca 的数据库应答状态查询,做实验和装订测试足够用了。

openssl ocsp -index ica/index.txt -port 8888 -rsigner ica/ica.crt -rkey ica/ica.key \
  -CA ica/ica.crt -nrequest 1 &
openssl ocsp -issuer ica/ica.crt -cert old.crt -url http://127.0.0.1:8888 -CAfile root.crt
Response verify OK
old.crt: revoked
    This Update: Nov  9 18:19:28 2026 GMT
    Reason: keyCompromise
    Revocation Time: Nov  9 18:18:25 2026 GMT

-port 只接受端口号(写成 127.0.0.1:8888 会报错),-nrequest 1 表示应答一次就退出。它是单线程的,不适合生产环境。私有 CA 和 index.txt 的搭建见搭建私有 CA。

常见问题

openssl x509 -ocsp_uri 什么都不输出,是证书有问题吗?

不是,只说明证书的 AIA 扩展里没有 OCSP 地址。CA/浏览器论坛把 OCSP 改为公网 CA 的可选项之后,多家 CA 已经不再提供;Let's Encrypt 从 2025 年 5 月 7 日起签发的证书就没有 OCSP 地址。改看 CRL 分发点即可。

Nginx 还要不要开 OCSP Stapling?

证书带 OCSP 地址时开着没坏处,还能替访客省一次查询。证书没有 OCSP 地址(例如现在的 Let's Encrypt 证书)时,Nginx 没东西可装订,只会在日志里给出警告,可以对这些站点关闭 ssl_stapling。宝塔面板生成的 Nginx 配置里如果带着 ssl_stapling,看到这类警告不必紧张。

浏览器会为每个网站下载 CRL 吗?

不会。Chrome 用 CRLSet,Firefox 用 CRLite,都是浏览器厂商根据各家 CA 的 CRL 汇总压缩后推送给浏览器的。直接查 OCSP、下载 CRL 的主要是浏览器以外的软件。详见 OCSP 与 CRL 原理。

资料来源

  1. OpenSSL 手册:openssl-ocsp
  2. OpenSSL 手册:openssl-crl
  3. RFC 6960:在线证书状态协议 OCSP
  4. RFC 5280:证书与 CRL 规范
  5. Let's Encrypt:Ending OCSP Support in 2025