利用 OpenSSL 搭建自签 SSL 证书的 OCSP 状态在线验证服务及 OCSP Stapling 说明

小助手读文章 00:00 / 00:00

温馨提示:
本文所述内容具有依赖性,可能因软硬条件不同而与预期有所差异,故请以实际为准,仅供参考。

在《正确使用 OpenSSL 自签发代码|邮件|域名|IP 证书》一文中,我们知道了如何使用 OpenSSL 来签发自签名证书,今天我们一起来学习如何为自签名的 SSL 证书启用 OCSP 在线吊销验证服务,开始本文之前建议先复习一下加深理解。

签发和吊销

简单回顾一下签发和吊销命令:

签发证书

openssl ca -in 127.0.0.1.csr -extfile 127.0.0.1.ext -days 365 -out 127.0.0.1.crt

吊销证书

# openssl ca -revoke 127.0.0.1.crt

生成吊销列表

# openssl ca -gencrl -out cer.crl

OCSP

CRL

在 《正确使用 OpenSSL 自签发代码|邮件|域名|IP 证书》 我们其实也说到了 CRL,这种方式的专业名称叫做证书吊销列表(英文:Certificate revocation list,缩写:CRL),是指尚未到期就被证书颁发机构吊销的数字证书的名单,这些在证书吊销列表中的证书不再会受到信任。

在 CRL 中包含本次更新日期和下次更新日期两个字段,以及所有已经吊销或挂起的数字证书信息。可以发现,CRL 依赖于 CA 公布周期,吊销延迟不可避免,并且依赖方要校验某个证书,必须到的 CA 目录服务器上下载整个 CRL,这将会造成网络资源的大量耗费。

减少吊销延迟和减少占用带宽总是矛盾的,因此其实现在很多证书颁发机构都启用了 OCSP 验证。

OCSP

在线证书状态协议(英文:Online Certificate Status Protocol,缩写:OCSP)是一个用于获取X.509 数字证书撤销状态的作为证书吊销列表(CRL)替代品的网际协议,解决了在公开密钥基础建设(PKI)中使用证书吊销列表而带来的多个问题。

与 CRL 相比,由于 OCSP 响应包含的信息较少,因此减轻了网络和客户端的资源负担;对于 OCSP 响应端,需要解析的信息更少,客户端提供的用于解析消息的库函数也更简单。

签发证书

默认配置下,自签发的证书是不包含吊销信息的,要实现吊销验证就需要在签发时就将吊销信息添加上去。

参考下方代码:

# cat 127.0.0.1.ext

keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName=@SubjectAlternativeName
#证书吊销列表 CRL
crlDistributionPoints=@crl_section
#在线证书状态协议 OCSP
authorityInfoAccess=@ocsp_section

[ SubjectAlternativeName ]
IP.1 = 127.0.0.1
DNS.1 = local.domain

[ crl_section ]
#证书吊销列表地址
URI.0 = http://local.domain/cer.crl

[ ocsp_section ]
#CA 证书
caIssuers;URI.0 = http://local.domain/cacert.pem
#验证地址
OCSP;URI.0 = http://local.domain/ocsp

注意,OCSP 地址应该是走 HTTP 协议。

搭建服务

在本例中,我们使用的地址是 http://local.domain,可以使用 Nginx 或 Apache 简单搭个 Web 服务,将 CA 证书和 CRL 放到网站目录下,然后子目录 ocsp 启用反代,指向本地的 OpenSSL OCSP 服务:

OCSP responder

即服务端负责验证证书的服务。需要指定响应签名的证书,这个证书与普通证书区别在于 extendedKeyUsage 需要增加 OCSPSigning,不赘述。

运行 OCSP responder:

# openssl ocsp -index index.txt -CA cacert.pem -port 8080 -text -rsigner default.crt -rkey default.key -timeout 60 -ignore_err -resp_no_certs
Waiting for OCSP client connections...

参数说明:

  • -ignore_err:忽略验证错误,若不添加,则在验证出现失败时(非本 CA 签发)就会自动退出运行;
  • -resp_no_certs:响应不输出证书信息,主要对 OCSP Stapling 有影响,后面详细说明。

Web 服务

# cat /etc/nginx/site-avaliable/default
...
server
 {
    listen 80;
    server_name local.domain;
    root /var/www/html/certificates;

    location ^~ /ocsp {
       proxy_pass http://127.0.0.1:8080;
    }
 }
...
# service nginx reload
Reload service nginx...  done

这里主要是为了与其他网站并行运行在 80 端口,所以 OCSP responder 运行在 8080,通过代理转发到 80 端口。

# ls /var/www/html/certificates
cacert.crt  cer.crl

在目录下存放 CA 证书和 吊销列表。

验证 OCSP

查看 ocsp 地址:

# openssl x509 -in 127.0.0.1.crt -noout -ocsp_uri
http://local.domain/ocsp

上面我们吊销了 127.0.0.1.crt,来验证一下响应:

# openssl ocsp -issuer cacert.pem -cert 127.0.0.1.crt -url http://local.domain/ocsp -resp_text -noverify
......
127.0.0.1.crt: revoked
    This Update: May 22 08:32:31 2020 GMT
    Revocation Time: May 22 08:30:50 2020 GMT

-noverify 参数表示不进行验证,如果要进行完整验证,应添加参数 -CAfile 值为信任的证书(一般为包含完整证书链的要验证的证书),-issuer 则是实际签发证书的签发 CA,比如我们自签的证书签发 CA 和根 CA 是一样的:

# openssl ocsp -CAfile cacert.pem -issuer cacert.pem -cert 127.0.0.1.crt -url http://local.domain/ocsp -resp_text -noverify
......
Response verify OK
127.0.0.1.crt: revoked
    This Update: May 22 08:32:31 2020 GMT
    Revocation Time: May 22 08:30:50 2020 GMT

正常运作的证书的响应是:

# openssl ocsp -issuer cacert.pem -cert default_certificate.crt -url http://local.domain:80 -resp_text -noverify
......
default_certificate.crt: good
    This Update: May 22 08:34:21 2020 GMT

而非本 CA 签发的证书的响应是:

# openssl ocsp -issuer cacert.pem -cert vircloud.net.crt -url http://local.domain:80 -resp_text -noverify
......
ssis.best.crt: unknown
    This Update: May 23 00:00:46 2020 GMT

可以很清楚地看到证书的状态,需要注意的是:

  • 1、当有发生证书签核、吊销时,OCSP responder 需要重启;
  • 2、由于 CA 证书是自签的,所以若客户端未添加信任,证书状态都无法自动进行验证;

OCSP Stapling

OCSP Stapling(OCSP 封装),是指服务端主动获取 OCSP 查询结果并随着证书一起发送给客户端,从而让客户端跳过自己验证的过程,提高 TLS 握手效率。

验证 OCSP Stapling 状态

# openssl s_client -connect 1.1.1.1:443 -servername vircloud.net -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"

如果结果是下面这样的,说明 OCSP Stapling 已成功开启可使用:

OCSP response:
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response

而这样的显然是未开启或者服务端配置错误:

OCSP response: no response sent

配置 OCSP Stapling

Nginx 中与 OCSP Stapling 有关的三个重要配置项:

ssl_stapling               on;
ssl_stapling_verify        on;
ssl_trusted_certificate    cacert.pem;

ssl_stapling 的作用自然不用说,ssl_trusted_certificate 指包含完整证书链的网站证书(顺序是网站证书在前,根证书在后),如果开启了 Nginx 的 ssl_stapling_verify,但没有正确配置 ssl_trusted_certificate,就会导致 OCSP Response 验证失败,OCSP Stapling 自然不会生效,就会出现前面 no response sent 的错误。

在 Nginx 中配置 ssl_stapling on 并 reload 后,Nginx 并不会马上获取 OCSP Response,它要等第一个请求过来,再发起异步 OCSP 请求,所以刚开始几个响应,很可能不带 OCSP Stapling。

有一种情况例外,就是 OCSP responder 没有返回 Certificate 证书信息(还记得前面说到的 -resp_no_certs 吗?),没有提供证书,Nginx 就无法验证其内容。对于这种情况,Nginx 直接忽略了 ssl_stapling_verify 参数,无论是否配置,都不执行 verify 操作,当然了,也完全不影响开启 OCSP Stapling。已知的有 COMODO、Let's Encrypt 的部分证书返回没有 Certificate。

可以在本地线测试一下看看,使用的证书对应的 OCSP responder 是否有返回证书:

# openssl ocsp -CAfile root.pem  -issuer cacert.pem -cert 127.0.0.1.crt -no_nonce -text -url http://local.domain/ocsp

如果返回值类似:

OCSP Request Data:
    Version: 1 (0x0)
......
OCSP Response Data:
    OCSP Response Status: successful (0x0)
......
Certificate:
.......
-----BEGIN CERTIFICATE-----
......
-----END CERTIFICATE-----
......

说明有返回证书,形如:

OCSP Request Data:
    Version: 1 (0x0)
......
OCSP Response Data:
    OCSP Response Status: successful (0x0)
.....

则说明没有返回证书。


参考文章:

1、《Create your own OCSP server
2、《在线证书状态协议
3、《从无法开启 OCSP Stapling 说起


ArmxMod for Typecho
个性化、自适应、功能强大的响应式主题

推广

 继续浏览关于 SSL代码证书openssl自签签名吊销ocsp在线验证 的文章

 本文最后更新于 2021/01/26 20:52:31,可能因经年累月而与现状有所差异

 引用转载请注明: VirCloud's Blog > 运维 > 利用 OpenSSL 搭建自签 SSL 证书的 OCSP 状态在线验证服务及 OCSP Stapling 说明