开启 OCSP Stapling

前言

昨天更新了博客,全站开启 HTTP/2 模式。基本设置完了以后,又发现了一些好玩的,今天这个算是补充说明吧。

介绍

先说说 OCSP 是个什么东东,其全名是 Online Certificate Status Protocol,简单说,就是一个可以检测 SSL 证书是否有效的在线证书状态查询协议。有些客户端在访问的时候,会通过 CA 提供的 OCSP URL 去查询证书的有效性,而这个过程实际上是一个阻断式的 HTTP 请求。客户端完成诸如 DNS 查询、TCP 链接建立、HTTP 请求、验证证书等操作后,用户可以开始正常浏览网站,而这中间可能会耗时很长,尤其是在中国这种奇葩的网络状况下,访问海外 CA 提供的 OCSP URL 更是如此。

而 OCSP Stapling 其实是服务器先去 CA 指定的 OCSP URL 获取 OCSP 查询结果,并将结果直接发送给客户端,免去客户端再去 CA 服务器验证的动作,从而提升访问时的连接速度和用户体验,说白了都是为了加速一丢丢。

OCSP 状态查询

先查看一下未修改 Nginx 配置之前的查询结果:

1
2
$ openssl s_client -connect tommy.net.cn:443 -servername tommy.net.cn -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"
OCSP response: no response sent

嗯,妥妥的,no response sent,表示服务器没有开启 OCSP 支持。下面是重新修改和配置好 Nginx 以后的 OCSP 查询结果:

1
2
3
4
5
$  openssl s_client -connect tommy.net.cn:443 -servername tommy.net.cn -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"
OCSP response:
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response

可以看到 OCSP 查询验证成功。

验证 OCSP Response

在配置 Nginx 配置文件之前,我们需要先在命令行验证一下,得到正确的 OCSP Response 先,首先是获得 OCSP URL:

1
2
$ openssl x509 -in cert.pem -ocsp_uri -noout
http://ocsp.startssl.com

嗯,一看就暴露了我使用 StartSSL 的事实,接下来验证 OCSP Response,证书签发用的是 StartSSL 的 Intermediate DV1 证书,cert.pem 是服务器证书:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
$ openssl ocsp -issuer intermediate.pem -cert cert.pem -no_nonce -text -url http://ocsp.startssl.com
OCSP Request Data:
Version: 1 (0x0)
Requestor List:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 5168159AB1999B3A55E860C022C9D519E0303D29
Issuer Key Hash: D7914E01C4B0BFF8C86793449CE733FAAD930CAF
Serial Number: 560E798B0AA4C055417AAB147A96F207
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: C = IL, O = StartCom Ltd., OU = StartCom Certification Authority, CN = StartCom Class 1 DV Server CA OCSP Responder
Produced At: Jul 25 10:07:29 2016 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 5168159AB1999B3A55E860C022C9D519E0303D29
Issuer Key Hash: D7914E01C4B0BFF8C86793449CE733FAAD930CAF
Serial Number: 560E798B0AA4C055417AAB147A96F207
Cert Status: good
This Update: Jul 25 10:07:29 2016 GMT
Next Update: Jul 29 10:17:29 2016 GMT

Signature Algorithm: sha256WithRSAEncryption
81:18:0b:fc:7e:3f:db:19:7d:c5:35:fa:8d:12:5a:5d:5b:24:
ea:2c:fe:69:c1:55:08:f7:8b:8b:51:f7:74:39:fa:43:dc:02:
7f:5e:b0:eb:d8:68:b4:4b:3e:a6:5c:55:d2:19:1e:84:66:86:
7d:e1:98:77:4c:6a:e1:61:a1:3b:08:a2:55:76:9e:79:8f:1c:
4f:d7:12:e1:75:92:9d:aa:85:0b:b5:bf:18:4d:e4:ba:bc:8a:
9c:35:4c:f4:46:f0:44:a5:fd:82:96:4e:7c:f2:56:95:d3:9b:
b5:47:98:6f:b1:47:3f:64:f3:4c:e0:71:f2:5c:df:71:80:8a:
05:b6:82:cf:ec:5a:86:53:55:9e:33:e1:1b:8b:44:ca:7f:5e:
24:a7:40:2b:fc:a2:9e:be:cb:a8:a1:ed:f0:45:3f:95:50:e8:
4e:0a:28:0a:0a:5a:68:75:cc:c7:17:57:67:93:3b:01:b1:40:
12:ef:c0:70:23:24:68:d2:28:34:65:68:4d:ac:98:05:e6:4b:
fb:09:b4:c7:46:0f:0d:b2:57:61:78:2e:f3:75:c5:48:1b:8a:
65:8e:5e:ff:40:cb:20:87:a1:c5:a7:c9:6d:c3:5f:63:db:9d:
c4:28:b0:9c:f8:14:70:dd:b5:0a:75:47:a1:2b:57:49:f3:cf:
41:cc:c0:cf
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
24:dd:c9:af:57:42:41:b8:ca:bc:8d:bf:96:9e:82:dc
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=IL, O=StartCom Ltd., OU=StartCom Certification Authority, CN=StartCom Class 1 DV Server CA
Validity
Not Before: Jun 10 01:59:42 2016 GMT
Not After : Sep 28 01:59:42 2016 GMT
Subject: C=IL, O=StartCom Ltd., OU=StartCom Certification Authority, CN=StartCom Class 1 DV Server CA OCSP Responder
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:ef:a0:56:07:82:f3:21:f8:a3:58:ca:7d:ef:f0:
51:f8:f0:67:4b:23:56:cb:d2:f5:5e:55:fa:d9:ef:
37:e2:c4:02:07:ba:a9:b2:d7:b3:67:bb:5e:fd:2f:
fd:a9:4d:80:94:1d:a4:7c:5f:5f:d4:fb:d5:c7:c8:
07:61:8a:4f:d5:6f:95:8b:43:33:78:f2:87:d6:a4:
43:c7:57:b9:fe:ea:2f:88:83:69:0b:25:6a:ba:67:
ad:03:ec:59:1a:9b:f9:2a:74:22:9e:44:aa:77:f6:
1f:15:94:22:9e:63:86:4c:00:3b:f3:fd:7c:6b:70:
f7:f5:17:32:c9:d1:96:46:80:86:be:9b:d2:7c:13:
db:3f:dd:2d:7f:cf:3f:9a:31:d1:35:b4:d8:ac:db:
6d:1f:87:10:ec:f7:98:b1:88:27:44:6d:4a:7a:91:
29:be:0f:bc:7f:33:d9:ac:ea:b2:f0:a6:eb:58:cb:
e6:29:05:6b:74:57:0b:d3:4b:3a:94:05:53:56:9c:
07:e4:53:5d:19:1d:42:04:76:78:b1:4a:d7:b2:99:
25:97:64:3b:51:5d:f3:f0:7d:c1:d8:f0:89:f8:b0:
4a:2c:37:df:b2:2a:e3:fa:dc:3a:f0:ec:fb:c3:a7:
74:7e:f5:3a:07:77:93:b3:42:1b:59:34:48:10:9a:
a7:6b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment, Key Agreement
X509v3 Extended Key Usage:
OCSP Signing
OCSP No Check:

X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
17:47:77:8E:AD:70:4C:F6:0C:E0:2F:9B:9E:86:38:54:9B:C2:15:18
X509v3 Authority Key Identifier:
keyid:D7:91:4E:01:C4:B0:BF:F8:C8:67:93:44:9C:E7:33:FA:AD:93:0C:AF

Authority Information Access:
OCSP - URI:http://ocsp.startssl.com
CA Issuers - URI:http://aia.startssl.com/certs/sca.server1.crt

X509v3 CRL Distribution Points:

Full Name:
URI:http://crl.startssl.com/sca-server1.crl

Signature Algorithm: sha256WithRSAEncryption
69:67:fa:4f:23:91:f0:56:61:b2:88:09:b4:eb:cd:d0:e7:f4:
22:a0:2c:f8:2d:cc:6f:7c:bd:1e:2e:17:8b:19:c5:be:3d:70:
90:6e:a6:94:2d:98:d9:a6:44:97:e6:53:c6:d9:9a:f8:1f:01:
f7:c3:9b:b4:22:4c:c0:81:72:49:f8:a7:bc:9d:18:49:47:d8:
7c:c6:5d:ef:3b:dc:b4:7c:3b:48:9a:d4:f3:ab:50:9c:fc:02:
75:5f:69:30:2a:bc:b4:65:d3:a2:02:b8:1b:4a:c9:ab:cf:d1:
03:38:cf:b3:df:a0:60:5b:e3:a1:a2:c7:f8:9d:9b:74:f3:08:
fa:8d:d8:21:b1:ec:65:b7:a0:cb:51:ec:2b:d7:01:0b:bb:54:
1b:63:af:df:f9:9e:ce:80:c8:09:60:57:ec:cd:f4:2b:d6:e4:
01:e4:00:00:59:ef:b1:75:28:96:82:47:16:0e:db:e5:3a:2e:
b5:2f:d5:9d:bf:f5:60:4c:02:fc:7e:f5:41:10:58:5d:9d:bd:
c8:1d:e7:02:71:82:60:28:c4:7f:1e:6f:95:c1:53:8b:f1:7e:
2a:46:ce:81:c6:18:e3:0b:e4:e7:df:aa:60:b0:80:10:60:86:
20:31:88:f5:46:8d:ba:d9:f9:7e:ed:1f:b3:16:ca:ba:ff:4f:
13:d3:9a:94
-----BEGIN CERTIFICATE-----
MIIEvzCCA6egAwIBAgIQJN3Jr1dCQbjKvI2/lp6C3DANBgkqhkiG9w0BAQsFADB4
MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEpMCcGA1UECxMg
U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJjAkBgNVBAMTHVN0YXJ0
Q29tIENsYXNzIDEgRFYgU2VydmVyIENBMB4XDTE2MDYxMDAxNTk0MloXDTE2MDky
ODAxNTk0MlowgYcxCzAJBgNVBAYTAklMMRYwFAYDVQQKDA1TdGFydENvbSBMdGQu
MSkwJwYDVQQLDCBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE1MDMG
A1UEAwwsU3RhcnRDb20gQ2xhc3MgMSBEViBTZXJ2ZXIgQ0EgT0NTUCBSZXNwb25k
ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvoFYHgvMh+KNYyn3v
8FH48GdLI1bL0vVeVfrZ7zfixAIHuqmy17Nnu179L/2pTYCUHaR8X1/U+9XHyAdh
ik/Vb5WLQzN48ofWpEPHV7n+6i+Ig2kLJWq6Z60D7Fkam/kqdCKeRKp39h8VlCKe
Y4ZMADvz/XxrcPf1FzLJ0ZZGgIa+m9J8E9s/3S1/zz+aMdE1tNis220fhxDs95ix
iCdEbUp6kSm+D7x/M9ms6rLwputYy+YpBWt0VwvTSzqUBVNWnAfkU10ZHUIEdnix
SteymSWXZDtRXfPwfcHY8In4sEosN9+yKuP63Drw7PvDp3R+9ToHd5OzQhtZNEgQ
mqdrAgMBAAGjggEzMIIBLzAOBgNVHQ8BAf8EBAMCA6gwEwYDVR0lBAwwCgYIKwYB
BQUHAwkwDwYJKwYBBQUHMAEFBAIFADAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQX
R3eOrXBM9gzgL5uehjhUm8IVGDAfBgNVHSMEGDAWgBTXkU4BxLC/+Mhnk0Sc5zP6
rZMMrzBvBggrBgEFBQcBAQRjMGEwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLnN0
YXJ0c3NsLmNvbTA5BggrBgEFBQcwAoYtaHR0cDovL2FpYS5zdGFydHNzbC5jb20v
Y2VydHMvc2NhLnNlcnZlcjEuY3J0MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly9j
cmwuc3RhcnRzc2wuY29tL3NjYS1zZXJ2ZXIxLmNybDANBgkqhkiG9w0BAQsFAAOC
AQEAaWf6TyOR8FZhsogJtOvN0Of0IqAs+C3Mb3y9Hi4XixnFvj1wkG6mlC2Y2aZE
l+ZTxtma+B8B98ObtCJMwIFySfinvJ0YSUfYfMZd7zvctHw7SJrU86tQnPwCdV9p
MCq8tGXTogK4G0rJq8/RAzjPs9+gYFvjoaLH+J2bdPMI+o3YIbHsZbegy1HsK9cB
C7tUG2Ov3/mezoDICWBX7M30K9bkAeQAAFnvsXUoloJHFg7b5ToutS/Vnb/1YEwC
/H71QRBYXZ29yB3nAnGCYCjEfx5vlcFTi/F+KkbOgcYY4wvk59+qYLCAEGCGIDGI
9UaNutn5fu0fsxbKuv9PE9OalA==
-----END CERTIFICATE-----
Response Verify Failure
139666926626464:error:27069065:OCSP routines:OCSP_basic_verify:certificate verify error:ocsp_vfy.c:126:Verify error:unable to get local issuer certificate
cert.pem: good
This Update: Jul 25 10:07:29 2016 GMT
Next Update: Jul 29 10:17:29 2016 GMT

可以看到证书验证成功,但是 Response Verify Failure,主要原因是无法找到本地证书签发者,其实这个指定 CA 证书便可,需要注意的是,这个 CA 证书必须是 CA Chained 证书,即包含 CA 和 Intermediate 的证书,这些证书根据不同的公司会有所不同,需要根据自己的情况实际调整。

1
2
3
4
5
6
7
8
9
$ openssl ocsp -CAfile chained.pem -issuer intermediate.pem -cert cert.pem -no_nonce -text -url http://ocsp.startssl.com
OCSP Request Data:

...

Response verify OK
cert.pem: good
This Update: Jul 25 06:14:54 2016 GMT
Next Update: Jul 29 06:24:54 2016 GMT

简化了中间结果,可以看到 OCSP 查询结果已经变成了 Response verify OK,表示一起都冇问题了。

配置 Nginx

其实,配置 Nginx 可以作弊,比如说使用 Mozilla SSL Configuration Generator,可以快速地按照需要生成各类常用 Web Server 的配置文件。我配置的时候,选择的配置如下:

  • Nginx
  • Intermediate
  • Server version: 1.9.5
  • OpenSSL Version: 1.0.2
  • HSTS Enabled

最后的配置结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
server {
listen 80 default_server;
listen [::]:80 default_server;

# Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;

# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /path/to/dhparam.pem;

# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;

# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;

# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;

## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /path/to/chained.pem;

resolver 8.8.8.8;

....
}

几个地方修改一下便可,cert.pem 是服务器证书,key.pem 是服务器私钥,chained.pem 是包含 CA 和 Intermediate 的证书。配置好后,重启服务器,再查询一下便发现 OCSP Stapling 已经生效了。注意,第一次请求的时候,服务器要去 CA OCSP URL 获取 OCSP Response,所以会提示没有 OCSP 查询结果,多运行一次就可以了。

1
2
3
4
5
$ openssl s_client -connect tommy.net.cn:443 -servername tommy.net.cn -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"
OCSP response:
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response

补充说明

除了用命令行以为,还有个不错的网站可以用来检测服务器证书配置情况,那就是 SSL LABS 了。比如说,要检测当前网站的配置情况点击这里就可以了,效果还是蛮不错的,还可以看到不同平台不同浏览器的兼容情况,下面是本站的检测评分:

参考文献