OCSP Stapling 是通过服务端客户端主动获取 OCSP 查询结果并随着证书一起发送给客户端,转而提高 TLS 握手效率。
国内使用 Let’s Encrypt 证书的网站或者服务非常多,毕竟不要钱。如果你不启用OCSP Stapling 的话,客户端访问服务端的时候,需要去验证证书。而在国内因为一些特殊原因Let’s Encrypt 的验证服务器连接过程会异常缓慢,过程可能持续十几秒,并且在iOS上这个问题特别严重。当然是用别的证书开启OCSP Stapling的话也会大大提高效率。
检查 OCSP Stapling 状态
最简单的办法是通过第三方查询网站查询https状态,即可验证OCSP Stapling状态。但这类网站功能十分强大,查询完毕经常需要几十秒。
使用 openssl 这个命令验证 OCSP Stapling 状态;
完整命令如下:
$ openssl s_client -connect wangshuashua.com:443 -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"
如果你的服务器上部署了多个 HTTPS 站点,可能还需要加上 -servername
参数启用 SNI:
$ openssl s_client -connect wangshuashua.com:443 -servername wangshuashua.com -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 ,如果您的证书是 Let’s Encrypt 家证书的可以忽略 ssl_trusted_certificate
参数;
因为 Let’s Encrypt 的 OCSP 服务不会返回 Certificate,所以使用 Let’s Encrypt 证书,开启 OCSP Stapling 无需配置 ssl_trusted_certificate
;
Let’s Encrypt 证书配置如下参数即可。
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 223.5.5.5 valid=300s ipv6=off;
resolver_timeout 5s;
其他证书配置需要附带 OCSP Stapling
验证文件啊,及 ssl_trusted_certificate 参数。
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate "/path/to/site.pem";
下面介绍如何通过 openssl 在本地获取证书 OCSP Response,生成 ssl_trusted_certificate
所需站点证书。
首先需要准备好待验证网站证书链上的所有证书。证书链一般由根证书、一个或多个中间证书、站点证书组成。根证书内置在操作系统或浏览器内(Firefox),可以直接导出,或者去各大 CA 官方下载;中间证书、站点证书在建立 TLS 连接时由服务端发送,可以这样获取:
$ openssl s_client -connect wangshuashua.com:443 -showcerts < /dev/null 2>&1
CONNECTED(00000003)
depth=2 C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
verify return:1
depth=1 C = BE, O = GlobalSign nv-sa, CN = GlobalSign Organization Validation CA - SHA256 - G2
verify return:1
depth=0 C = CN, ST = ZheJiang, L = HangZhou, O = "Alibaba (China) Technology Co., Ltd.", CN = *.alicdn.com
verify return:1
---
Certificate chain
0 s:/C=CN/ST=ZheJiang/L=HangZhou/O=Alibaba (China) Technology Co., Ltd./CN=*.alicdn.com
i:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
-----BEGIN CERTIFICATE-----
MIIG+DCCBeCgAwIBAgIMS62MvWfwokD9DEmpMA0GCSqGSIb3DQEBCwUAMGYxCzAJ
...
-----END CERTIFICATE-----
1 s:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
-----BEGIN CERTIFICATE-----
MIIEaTCCA1GgAwIBAgILBAAAAAABRE7wQkcwDQYJKoZIhvcNAQELBQAwVzELMAkG
...
-----END CERTIFICATE-----
---
Server certificate
subject=/C=CN/ST=ZheJiang/L=HangZhou/O=Alibaba (China) Technology Co., Ltd./CN=*.alicdn.com
issuer=/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3578 bytes and written 415 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: 9B0E1E0095F9AF922AF4BA051FD03A3359DE6424EB7545F8B15DE7E3B6B...
Session-ID-ctx:
Master-Key: B967E727C4C2C04E661B758669CA3360A810C0BB6FC17E995D9384C2C5FC...
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
TLS session ticket lifetime hint: 900 (seconds)
TLS session ticket:
0000 - c7 f3 15 16 ca 6f 94 ed-9e 9e 8e b7 f6 f1 53 b1 .....o........S.
....
Start Time: 1608743940
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
DONE
以上内容中 Certificate Chain 这一节,编号为 0 的证书是站点证书;编号为 1 的证书是中间证书。
将站点证书保存为 site.pem;中间证书保存为 intermediate.pem(如果有多个中间证书,按照子证书在上的顺序保存);再从系统中导出对应的根证书存为 root.pem。
通过站点获取证书的 OCSP 服务地址:
$ openssl x509 -in site.pem -noout -ocsp_uri
http://gz.symcd.com
现在万事具备,使用以下命令即可获得站点证书的 OCSP Response:
$ openssl ocsp -issuer intermediate.pem -cert site.pem -no_nonce -text -url http://gz.symcd.com
OCSP Request Data:
Version: 1 (0x0)
Requestor List:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 7C8E4E54532DB74C235073AAF1CDCF2C2423F86B
Issuer Key Hash: F3B5560CC409B0B4CF1FAAF9DD2356F077E8A1F9
Serial Number: 5A26
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: 87BAEBE8F7B12700EC9CD1A04EE0E123E57D809E
Produced At: Mar 11 07:56:56 2016 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 7C8E4E54532DB74C235073AAF1CDCF2C2423F86B
Issuer Key Hash: F3B5560CC409B0B4CF1FAAF9DD2356F077E8A1F9
Serial Number: 5A26
Cert Status: good
This Update: Mar 11 07:56:56 2016 GMT
Next Update: Mar 18 07:56:56 2016 GMT
Signature Algorithm: sha1WithRSAEncryption
8a:81:d6:a5:aa:8a:92:05:6f:39:97:f5:da:d0:bc:06:86:f2:
... ...
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 8 (0x8)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=GeoTrust Inc., CN=RapidSSL SHA256 CA - G4
Validity
Not Before: Jul 10 18:18:29 2015 GMT
Not After : May 22 18:18:29 2016 GMT
Subject: CN=RapidSSL SHA256 CA - G4 OCSP Responder
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:9d:e9:7b:75:81:1e:00:ab:b3:b4:cc:3f:a3:2d:
... ...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:F3:B5:56:0C:C4:09:B0:B4:CF:1F:AA:F9:DD:23:56:F0:77:E8:A1:F9
OCSP No Check:
X509v3 Subject Key Identifier:
87:BA:EB:E8:F7:B1:27:00:EC:9C:D1:A0:4E:E0:E1:23:E5:7D:80:9E
X509v3 Extended Key Usage:
OCSP Signing
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature
X509v3 Subject Alternative Name:
DirName:/CN=TGV-C-26
Signature Algorithm: sha256WithRSAEncryption
... ...
-----BEGIN CERTIFICATE-----
MIIDnTCCAoWgAwIBAgIBCDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJVUzEW
... ...
bmgyvaosG4GykSUnasMqfbA=
-----END CERTIFICATE-----
Response Verify Failure
140735166222416:error:27069065:OCSP routines:OCSP_basic_verify:certificate verify error:ocsp_vfy.c:138:Verify error:unable to get local issuer certificate
site.pem: good
This Update: Mar 11 07:56:56 2016 GMT
Next Update: Mar 18 07:56:56 2016 GMT
可以看到,自己获取的 OCSP Response 和服务端发送的 OCSP Stapling 完全一致,响应中的 Cert Status: good
表示证书合法。
将根证书、全部中间证书按照子证书在上的顺序,保存为 chain.pem
。这些就是我们需要在Nginx 配置文件里面需要的 ssl_trusted_certificate
文件了,可以通过以下代码验证获取的 chain.pem
证书是否正确。
$ openssl ocsp -CAfile chain.pem -issuer intermediate.pem -cert site.pem -no_nonce -text -url http://gz.symcd.com
这下,最终的结果就是 Response verify OK 了。
后话
在 Nginx 中配置 ssl_stapling on
并 reload 后,Nginx 并不会马上获取 OCSP Response,它要等第一个请求过来,再发起异步 OCSP 请求,所以刚开始几个响应,很可能不带 OCSP Stapling。另外,有时候由于 OCSP 域名无法解析,或者服务器无法访问造成 OCSP Response 获取失败,也会导致 OCSP Stapling 无法生效。这是首先需要排查的地方,一般在 Nginx 的 error_log 中会有这样的错误:
[error] 5225#0: example.com could not be resolved (110: Operation timed out) while requesting certificate status, responder: example.com
如果 OCSP Response 包含了 Certificate 信息,并且 Nginx 配置了 ssl_stapling_verify on
,那么需要确保正确配置了 ssl_trusted_certificate
参数,这个参数应该指向一个包含根证书、中间证书的文件(顺序是子证书在上、父证书在下),否则 OCSP Stapling 无法生效。这时候 Nginx 的 error_log 中会出现类似这样的错误:
[error] 4832#0: OCSP_basic_verify() failed (SSL: error:27069065:OCSP routines:OCSP_basic_verify:certificate verify error:Verify error:unable to get local issuer certificate) while requesting certificate status, responder: example.com
如果证书 OCSP Response 没有包含 Certificate 信息,例如 COMODO、Let’s Encrypt 家的部分证书,那么 ssl_stapling_verify
和 ssl_trusted_certificate
两个配置可以忽略,完全不影响开启 OCSP Stapling。
扩充阅读: