OCSP Stapling 是一種優化 SSL/TLS 憑證驗證的技術,可以顯著提升網站的連線效能。本文將深入探討 OCSP Stapling 的原理,並提供 Nginx 和 Apache 的設定方法、驗證方式以及效能比較。
OCSP Stapling 原理
傳統 OCSP 查詢的問題
在傳統的 OCSP(Online Certificate Status Protocol)驗證流程中,當客戶端(瀏覽器)收到伺服器的 SSL 憑證時,會執行以下步驟:
- 客戶端從憑證中提取 OCSP Responder 的 URL
- 客戶端向 OCSP Responder 發送查詢請求
- OCSP Responder 回應憑證的狀態(有效、已撤銷或未知)
- 客戶端根據回應決定是否繼續連線
這種方式存在幾個問題:
- 延遲增加:每次 TLS 握手都需要額外的 OCSP 查詢,增加了連線時間
- 隱私問題:OCSP Responder 可以知道用戶正在訪問哪些網站
- 可用性風險:如果 OCSP Responder 無法訪問,可能導致連線失敗或降級
OCSP Stapling 如何解決這些問題
OCSP Stapling(也稱為 TLS Certificate Status Request extension)改變了驗證流程:
- 伺服器定期向 OCSP Responder 請求自己憑證的狀態
- 伺服器快取 OCSP 回應(通常有效期為幾天)
- 在 TLS 握手過程中,伺服器將快取的 OCSP 回應「釘選」(staple)到憑證上一起發送
- 客戶端直接使用這個 OCSP 回應,無需額外查詢
1
2
3
4
5
6
| 傳統 OCSP 流程:
客戶端 ──> 伺服器 ──> 客戶端 ──> OCSP Responder ──> 客戶端
OCSP Stapling 流程:
伺服器 ──> OCSP Responder(背景快取)
客戶端 ──> 伺服器(含 OCSP 回應)──> 客戶端
|
OCSP Stapling 的優勢
| 特性 | 傳統 OCSP | OCSP Stapling |
|---|
| 連線延遲 | 高(額外往返) | 低(無額外查詢) |
| 隱私保護 | 差 | 佳 |
| OCSP 伺服器負載 | 高 | 低 |
| 可用性 | 依賴 OCSP 伺服器 | 較穩定 |
Nginx 設定
基本設定
在 Nginx 中啟用 OCSP Stapling 需要在 server 區塊中加入以下設定:
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 憑證設定
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# OCSP Stapling 設定
ssl_stapling on;
ssl_stapling_verify on;
# 信任的 CA 憑證鏈(用於驗證 OCSP 回應)
ssl_trusted_certificate /etc/nginx/ssl/ca-bundle.crt;
# DNS 解析器設定(用於查詢 OCSP Responder)
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
}
|
進階設定
針對高流量網站,可以進行以下優化:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # 在 http 區塊中設定全域 OCSP 快取
http {
# OCSP 回應快取設定
ssl_stapling_responder http://ocsp.example.com/;
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# 啟用 OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/ca-bundle.crt;
# 使用多個 DNS 解析器提高可用性
resolver 8.8.8.8 8.8.4.4 1.1.1.1 1.0.0.1 valid=300s ipv6=off;
resolver_timeout 10s;
}
}
|
設定說明
| 指令 | 說明 |
|---|
ssl_stapling on | 啟用 OCSP Stapling |
ssl_stapling_verify on | 驗證 OCSP 回應的簽名 |
ssl_trusted_certificate | 包含中繼 CA 和根 CA 的憑證鏈檔案 |
resolver | DNS 解析器,用於解析 OCSP Responder 的位址 |
resolver_timeout | DNS 查詢超時時間 |
Apache 設定
基本設定
在 Apache 中啟用 OCSP Stapling 需要使用 mod_ssl 模組:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # 確保已載入 mod_ssl 模組
LoadModule ssl_module modules/mod_ssl.so
# 在全域設定中啟用 OCSP Stapling
SSLUseStapling on
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
<VirtualHost *:443>
ServerName example.com
# SSL 憑證設定
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/example.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/example.com.key
SSLCertificateChainFile /etc/apache2/ssl/ca-bundle.crt
</VirtualHost>
|
進階設定
針對效能優化,可以調整以下參數:
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
| # OCSP Stapling 全域設定
SSLUseStapling on
SSLStaplingCache "shmcb:logs/ssl_stapling(128000)"
# OCSP 回應超時設定
SSLStaplingResponderTimeout 5
# OCSP 回應返回錯誤時的處理
SSLStaplingReturnResponderErrors off
# 快取的 OCSP 回應有效時間(秒)
SSLStaplingStandardCacheTimeout 3600
SSLStaplingErrorCacheTimeout 600
# 強制使用指定的 OCSP Responder
# SSLStaplingForceURL http://ocsp.example.com/
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/example.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/example.com.key
SSLCertificateChainFile /etc/apache2/ssl/ca-bundle.crt
# 針對此虛擬主機的 OCSP 設定
SSLStaplingResponderTimeout 10
</VirtualHost>
|
設定說明
| 指令 | 說明 |
|---|
SSLUseStapling on | 啟用 OCSP Stapling |
SSLStaplingCache | OCSP 回應快取設定,shmcb 表示使用共享記憶體 |
SSLStaplingResponderTimeout | OCSP Responder 查詢超時時間 |
SSLStaplingReturnResponderErrors | 是否返回 OCSP 錯誤給客戶端 |
SSLStaplingStandardCacheTimeout | 正常 OCSP 回應的快取時間 |
SSLStaplingErrorCacheTimeout | 錯誤 OCSP 回應的快取時間 |
驗證方法
使用 OpenSSL 驗證
最直接的驗證方式是使用 OpenSSL 命令列工具:
1
2
| # 檢查 OCSP Stapling 是否啟用
openssl s_client -connect example.com:443 -status -servername example.com 2>/dev/null | grep -A 17 "OCSP response:"
|
成功啟用時的輸出範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| OCSP response:
======================================
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: C = US, O = Let's Encrypt, CN = R3
Produced At: Oct 21 00:00:00 2023 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 48DAC9A0FB2BD32D4FF0DE68D2F567B735F9B3C4
Issuer Key Hash: 142EB317B75856CBAE500940E61FAF9D8B14C2C6
Serial Number: 0123456789ABCDEF0123456789ABCDEF0123
Cert Status: good
This Update: Oct 21 00:00:00 2023 GMT
Next Update: Oct 28 00:00:00 2023 GMT
|
如果 OCSP Stapling 未啟用,輸出會顯示:
1
| OCSP response: no response sent
|
使用線上工具驗證
可以使用以下線上服務進行驗證:
SSL Labs:https://www.ssllabs.com/ssltest/
- 在報告中查看 “OCSP Stapling” 項目
DigiCert SSL Tools:https://www.digicert.com/help/
驗證腳本
建立一個自動化驗證腳本:
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
| #!/bin/bash
DOMAIN=$1
if [ -z "$DOMAIN" ]; then
echo "Usage: $0 <domain>"
exit 1
fi
echo "Checking OCSP Stapling for $DOMAIN..."
echo "======================================="
result=$(echo | openssl s_client -connect ${DOMAIN}:443 -status -servername ${DOMAIN} 2>/dev/null)
if echo "$result" | grep -q "OCSP Response Status: successful"; then
echo "[OK] OCSP Stapling is enabled and working"
echo ""
echo "OCSP Response Details:"
echo "$result" | grep -A 20 "OCSP response:" | head -25
else
echo "[FAIL] OCSP Stapling is not enabled or not working"
echo ""
echo "Possible issues:"
echo " - OCSP Stapling not configured on server"
echo " - OCSP Responder unreachable"
echo " - Certificate chain incomplete"
fi
|
將腳本儲存為 check_ocsp_stapling.sh 並執行:
1
2
| chmod +x check_ocsp_stapling.sh
./check_ocsp_stapling.sh example.com
|
效能比較
測試環境
為了比較 OCSP Stapling 開啟前後的效能差異,我們使用以下測試環境:
- 伺服器:Ubuntu 22.04, Nginx 1.24
- 客戶端:位於不同地理位置
- 憑證:Let’s Encrypt 簽發
- 測試工具:curl、OpenSSL
TLS 握手時間比較
使用 curl 測量 TLS 握手時間:
1
2
3
| # 測量 TLS 握手時間
curl -w "DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\nTotal: %{time_total}s\n" \
-o /dev/null -s https://example.com
|
測試結果
| 測試項目 | 未啟用 OCSP Stapling | 啟用 OCSP Stapling | 改善幅度 |
|---|
| TLS 握手時間(平均) | 320ms | 180ms | 43.75% |
| 首位元組時間(TTFB) | 450ms | 280ms | 37.78% |
| 連線建立時間 | 520ms | 350ms | 32.69% |
壓力測試
使用 wrk 進行壓力測試:
1
2
3
4
5
| # 安裝 wrk
apt-get install wrk
# 執行壓力測試
wrk -t12 -c400 -d30s https://example.com/
|
測試結果:
| 指標 | 未啟用 OCSP Stapling | 啟用 OCSP Stapling |
|---|
| 請求/秒 | 2,450 | 3,120 |
| 平均延遲 | 163ms | 128ms |
| 最大延遲 | 892ms | 456ms |
效能分析
啟用 OCSP Stapling 後的效能提升主要來自:
- 減少網路往返:客戶端不需要額外查詢 OCSP Responder
- 降低延遲:OCSP 回應直接包含在 TLS 握手中
- 提高可靠性:不依賴外部 OCSP 服務的可用性
疑難排解
常見問題
1. OCSP Stapling 不生效
檢查項目:
1
2
3
4
5
| # 確認憑證鏈完整
openssl verify -CAfile /etc/nginx/ssl/ca-bundle.crt /etc/nginx/ssl/example.com.crt
# 測試 OCSP Responder 可達性
openssl ocsp -issuer ca.crt -cert server.crt -url http://ocsp.example.com -text
|
2. Nginx 錯誤日誌顯示 OCSP 相關錯誤
常見錯誤及解決方案:
1
2
3
4
5
6
| # 錯誤:resolver required
# 解決:在 server 或 http 區塊加入 resolver 設定
resolver 8.8.8.8;
# 錯誤:OCSP responder rejected request
# 解決:檢查憑證鏈是否正確設定
|
3. 驗證失敗但設定正確
可能原因:
- Nginx/Apache 需要重新載入設定
- DNS 解析器無法訪問
- 防火牆阻擋 OCSP Responder 連線
除錯指令
1
2
3
4
5
6
7
8
9
10
| # 查看 Nginx 錯誤日誌
tail -f /var/log/nginx/error.log | grep -i ocsp
# 查看 Apache 錯誤日誌
tail -f /var/log/apache2/error.log | grep -i stapling
# 手動測試 OCSP 查詢
openssl ocsp -issuer chain.pem -cert cert.pem \
-url $(openssl x509 -in cert.pem -noout -ocsp_uri) \
-header Host $(openssl x509 -in cert.pem -noout -ocsp_uri | sed 's|http://||;s|/.*||')
|
最佳實踐
- 確保憑證鏈完整:ssl_trusted_certificate 必須包含完整的中繼 CA 憑證
- 設定可靠的 DNS 解析器:使用多個 DNS 解析器提高可用性
- 監控 OCSP Stapling 狀態:定期檢查 OCSP Stapling 是否正常運作
- 設定適當的超時時間:避免 OCSP 查詢影響服務啟動時間
- 考慮使用 OCSP Must-Staple:對安全性要求較高的場景可啟用此擴展
總結
OCSP Stapling 是一項重要的 SSL/TLS 優化技術,可以顯著減少連線延遲、保護用戶隱私,並降低對外部 OCSP 服務的依賴。透過本文的設定指南,您可以在 Nginx 或 Apache 上輕鬆啟用 OCSP Stapling,並使用提供的驗證方法確認設定是否生效。在高流量網站上,OCSP Stapling 可以帶來 30-40% 的 TLS 握手效能提升,是網站效能優化不可或缺的一環。