温馨提示:
本文所述内容具有依赖性,可能因软硬条件不同而与预期有所差异,故请以实际为准,仅供参考。
在《正确使用 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 说起》
AWS CloudFront CDN 详细图文部署教程及自选优质 IP 方法 | 我的文本