什么是 OCSP Must-Staple#
OCSP Must-Staple(RFC 6066 第 8 节定义)是一种证书扩展,用于告知客户端证书颁发机构(CA)要求在 TLS 握手时必须提供 OCSP 响应。通过此扩展,客户端可以拒绝与无法提供有效 OCSP 响应(或 OCSP stapling)的服务器建立连接。
作用机制#
当证书包含 Must-Staple 扩展时:
- 服务器端:必须在 TLS 握手时通过 OCSP stapling 发送预缓存的 OCSP 响应
- 客户端验证:支持 Must-Staple 的客户端会检查 stapled OCSP 响应是否存在且有效
- 连接拒绝:如果服务器未提供有效的 OCSP 响应,客户端将拒绝建立连接
安全价值#
Must-Staple 主要防止以下攻击场景:
- 防止吊销绕过:攻击者无法通过阻止客户端直接查询 OCSP 服务器来绕过证书吊销检查
- 减少客户端到 CA 的网络请求:通过 stapling 减少延迟和隐私泄露
- 强制证书状态检查:确保每次连接都进行证书有效性验证
验证证书是否包含 Must-Staple#
使用 Let’s Encrypt 证书(推荐)#
Let’s Encrypt 签发的证书默认包含 Must-Staple 扩展。可以使用以下方式验证:
1
2
|
# 查看证书扩展信息
openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -text | grep -i "ocsp"
|
如果证书包含 Must-Staple,会看到类似输出:
1
2
3
|
OCSP Must-Staple:
TLS Feature:
status_request
|
或者使用 OID 直接检查:
1
|
openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -text | grep -A2 "1.3.6.1.5.5.7.1.24"
|
使用 OpenSSL 查看完整扩展#
1
|
openssl x509 -in your_certificate.pem -noout -text
|
在输出中查找 TLS Feature 扩展:
1
2
|
X509v3 TLS Feature:
TLS Feature: status_request
|
服务器配置#
Nginx 配置#
Nginx 从 1.3.7 版本开始支持 OCSP stapling。配置示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# 启用 OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# 解析 OCSP 响应器(使用可信 DNS)
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
}
|
配置说明:
ssl_stapling on:启用 OCSP stapling
ssl_stapling_verify on:验证 stapling 响应
resolver:指定 DNS 服务器用于解析 OCSP 响应器地址
valid=300s:缓存 DNS 解析结果 300 秒
Apache 配置#
1
2
3
4
5
6
7
8
9
10
11
12
|
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /path/to/fullchain.pem
SSLCertificateKeyFile /path/to/privkey.pem
# 启用 OCSP stapling
SSLUseStapling on
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
SSLStaplingStandardCacheTimeout 3600
SSLStaplingErrorCacheTimeout 600
</VirtualHost>
|
测试配置#
配置完成后,重启服务并测试:
1
2
3
4
5
|
# 重启 Nginx
nginx -t && nginx -s reload
# 或重启 Apache
apachectl graceful
|
验证 Must-Staple 配置#
使用 OpenSSL s_client 测试#
1
2
|
# 测试 OCSP stapling 是否正常工作
echo | openssl s_client -connect example.com:443 -servername example.com -status 2>&1 | grep -A5 "OCSP Response"
|
正常输出示例:
1
2
3
4
5
|
OCSP Response Status: successful (0x0)
OCSP Response Data:
OCSP Response IDs:
OCSP Response ID: (null)
Cert Status: good
|
使用 testssl.sh 检测#
1
2
|
# 检测服务器 Must-Staple 支持情况
testssl --standard example.com | grep -i "must-staple"
|
使用 curl 验证#
1
2
3
|
# curl 7.68.0+ 支持 Must-Staple
# 如果服务器未正确配置 OCSP stapling,会显示警告
curl -vI https://example.com/ 2>&1 | grep -i "staple"
|
注意事项#
兼容性考虑#
- 旧版客户端:不支持 Must-Staple 的客户端会忽略此扩展,正常建立连接
- 服务器必须支持 stapling:如果证书包含 Must-Staple 但服务器未配置 OCSP stapling,支持该特性的客户端会拒绝连接
- OCSP 响应器可用性:确保服务器能成功获取并缓存 OCSP 响应
维护建议#
- 监控 OCSP 响应:定期检查 stapling 是否正常工作
- 证书续期:Let’s Encrypt 证书续期后自动保留 Must-Staple
- 故障排查:如果客户端突然无法连接,首先检查 OCSP stapling 状态
常见问题#
Q: Must-Staple 会导致连接失败吗?
A: 仅当服务器无法提供有效的 OCSP 响应时才会失败。正确配置 OCSP stapling 后不会影响正常连接。
Q: 如何判断证书是否包含 Must-Staple?
A: 使用 openssl x509 -in cert.pem -noout -text | grep "TLS Feature" 检查是否存在 status_request。
Q: 可以为已有证书添加 Must-Staple 吗?
A: 不能。Must-Staple 是证书签发时嵌入的扩展,只能在重新签发证书时添加。
完整配置示例#
以下是一个完整的 Nginx 配置示例,包含现代 TLS 最佳实践:
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
|
server {
listen 443 ssl http2;
server_name example.com;
# 证书路径(Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# OCSP Stapling 配置
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s ipv6=off;
resolver_timeout 5s;
# TLS 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS(可与 Must-Staple 配合使用)
add_header Strict-Transport-Security "max-age=63072000" always;
# 其他安全头
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
}
|
参考来源#