Featured image of post 淺談 OCSP Stapling

淺談 OCSP Stapling

自從把部落格系統換成 Wordpress 以後,又是快取,又是精簡,又是各種替換,為了最佳化網站的速度不可不謂花了一番心思,然而在 iPhone 上,我的網站的開啓速度卻依然時快時慢。在之前兩個月裏,我一直認為是伺服器的效能問題所致。直到有一天我看到並且為網站部署了 OCSP Stapling。

為什麼偏偏在 iPhone 上就開啓慢?

你可能已經注意到我使用了「開啓」而非「載入」,如果你呼叫 iPhone 上 Safari 的開發者模式檢視一個網頁的 Handshake 時間,你就會發現一個不容忽視的 1 秒,至於這一秒都花在了哪裏,我們先來看看 OCSP 究竟是什麼。

OCSP 的概念

先從 SSL 證書的有效期説起

曾經我有一個困惑,為什麼沒有永久有效的 SSL 證書?難道是單純因為商業原因?其實並不是,主要原因是為了安全。每次簽發機構(CA)簽發 SSL 證書時,CA 都會為這個 SSL 證書生成一個私鑰。就像家裏任何一把鑰匙一樣,HTTPS 證書的私鑰有丟失、泄露的風險,當網站的私鑰丟失時,網站應該向證書 CA 申請將他們的證書加入到證書吊銷列表(CRL)裏。當用戶訪問 https 站點時,瀏覽器會自動向 CA 請求吊銷列表,如果用戶訪問的站點提供的證書在 CRL 裏,瀏覽器就不信任這個證書,因為私鑰泄漏後,攻擊者可能擁有同樣的證書。

所以,如果證書永久有效,隨着越來越多的私鑰丟失,吊銷列表也越來越大(因為只有加進去的,沒有剔出去的),這既給 CA 的伺服器增加流量壓力,也會增加瀏覽器需要下載的資料量。而一旦有效期只有一年或幾年,那麼CA就可以將那些已經過期了的證書從 CRL 裏剔除,因為反正瀏覽器也不信任過期證書。這種問題也就隨之消失,於是,今天看到的證書,有效期都隨着安全等級的提高而加長,但除非自籤,沒有永久有效的證書。

這和 OCSP 有什麼關係?

OCSP 即 Oline Certificate Status Protocol,是用於替代 CRL 的協議,解決了一些 CRL 協議存在的問題,以下資訊來譯自 Wikipedia:

OCSP 響應通常比典型的 CRL 響應更小,這意味着對於客户端和伺服器更小的網絡負擔。

OCSP 響應中需要解析的資料更少,因此客户端需要的執行庫比解析典型的 CRL 響應更少更簡單

OCSP 中,伺服器可以記錄主機在何時驗證過特定的證書,由於請求不強制加密,相關資訊可能被第三方獲取。

簡單來説,OCSP 做的就是 CRL 的事——驗證這個網站的 https 證書是否處於被吊銷的狀態。

所以為什麼開啓慢?

我們搭建個人網站時大都沒有很高的預算,例如我的網站原本託管在免費的 Github Pages 上,預算能省則省,更別提動輒幾千一年的 SSL 證書了。於是你看到的非商業性質的個人網站大都採用了免費的 Let’s Encrypt 證書。而 Let’s Encrypt 的 OCSP 伺服器 ocsp.int-x3.letsencrypt.org 線路非常垃圾,實測中部地區聯通 traceroute 以供蔘考:

Let’s Encrypt OCSP伺服器的拉胯線路

可以看到伺服器在香港,線路卻繞美國。這導致 一個很簡單的 OCSP 查詢請求需要 1 秒的時間來返回結果。這意味着無論你的伺服器效能有多強,網絡延遲有多低,只要部署的證書是 Let’s Encrypt,網站在 iPhone 上的載入時間就絕對不會快過一秒。這還不是最壞的情況,因為各種莫名其妙的原因,Let’s Encrypt 的 OCSP 伺服器域名會時不時的被 GFW 透過 DNS 污染等方式阻斷,這就導致客户端在一部分時間裏根本無法查詢 OCSP。

但為什麼只有 iPhone 會載入慢呢?

OCSP 協議有一個很要命的問題:用 https 的人越來越多,驗證證書有效性的需求自然會越來越大,OCSP 伺服器難道硬扛訪問量?當然不是,不同瀏覽器都會有不同的 OCSP 驗證超時時間,超時就先預設證書有效繼續進行訪問。但是有些"「注重用戶體驗」 的瀏覽器,比如 Chrome,自己在瀏覽器內部做了個本地列表,透過每次瀏覽器更新實現列表更新。直接查本地的列表速度就非常快了,當然也不存在什麼 CA 的 OCSP 伺服器被遮蔽的問題。缺點是並非實時更新。但並非所有瀏覽器都是所謂「注重用戶體驗」的瀏覽器,比如 Safari 就預設開啓 OCSP 驗證。自然無法避免這種中國特色的問題。Chrome 在全球有超過 70% 的市佔率,而受 Chromium 開源專案的影響,國內一眾「安全」「極速」瀏覽器都不存在這種問題,這幾乎覆蓋了國內桌面端所有用戶羣體。而蘋果要求包括 Chrome 在內的所有 iOS 應用都要使用 Webkit 核心,這直接乾死了所有的 iPhone 用戶。

怎麼解決?

總不可能要求所有 iPhone 用戶都自己關掉 OCSP 吧?那麼解決方法就是——換證書。怎麼可能,要是我真換了證書你也就看不到這篇文章了。雖然換證書,比如 Trust Asia 證書的確可以解決問題。但我不想因為換一個證書而告別 Let’s Encrypt 自動續期和支援泛域名的特性。

終於可以談到 OCSP Stapling 了,即 OCSP 封裝,想要開啓 OCSP Stapling 非常簡單:首先到亞洲誠信提供的 https 檢測服務檢測自己的證書鏈是否完整,若是不完整則修復證書鏈後將修復好的證書重新部署,完成操作後在 Nginx 配置里加上如下兩行:

1
2
ssl_stapling on;
ssl_stapling_verify on;

然後重啓 Nginx 服務,大功告成。由於我自己使用的是 Nginx,Apache 請自行搜尋相關方法。

然後,iPhone 用戶也能愉快的訪問你的網站而無需忍受惱人的 GFW 干擾 Let’s Encrypt 的 OCSP 伺服器。

那麼效果如何呢?

開啓OCSP Stapling前排隊時間超過1秒

開啓OCSP Stapling後排隊時間僅200毫秒

可以看到,開啓 OCSP Stapling 後,查詢驗證結果所需要的時間大幅縮短,反映到網站開啓速度上是非常明顯的感知。

什麼東西這麼牛逼?

OCSP 封裝,顧名思義,即伺服器快取 OCSP 伺服器的驗證結果,並且在與客户端 SSL 握手時直接傳送快取結果。

OCSP裝訂,是TLS證書狀態查詢擴充套件,作為線上證書狀態協議的替代方法對X.509證書狀態進行查詢,伺服器在TLS握手時傳送事先快取的OCSP響應,用戶只要驗證該響應的時效性而不用再向數字證書認證機構(CA)傳送請求,可以加快握手速度。

我的伺服器線路雖然亦非很好,但比 Let’s Encrypt 的弟中弟線路好到不知道哪裏去了。開啓 OCSP Stapling 後,客户端只需要驗證伺服器事先快取的 OCSP 查詢結果的有效性,免去了向“神最佳化”的伺服器發請求的痛苦,速度自然會快上一大截,在有 OCSP 強制驗證的瀏覽器上初次開啓網頁的效果尤為明顯,統計資料顯示,在開啓 OCSP Stapling 後,新訪客量明顯有所提高,大概是拜 OCSP Stapling 節省的大量握手時間所賜。

為什麼不預設開啓 OCSP Stapling?

聽上去 OCSP Stapling 簡直就是完美的萬金油最佳化——每個網站都開啓 OCSP Stapling,既提升用戶的訪問體驗,也為 OCSP 伺服器減輕負擔。那為什麼新的 Nginx 配置檔案不預設開啓 OCSP Stapling 呢?其實這是一個很簡單的問題。

  • 不是所有網站都有 SSL 證書
  • OCSP Stapling 並非在所有情況下都能提供更好的訪問體驗
  • 現存方案中 OCSP 並不是唯一的證書驗證方案
  • 引入新功能時通常是需要謹慎的,Nginx 用戶羣體非常複雜,不同用戶不同需求

蔘考

  1. 為什麼https證書要設有有效期?
  2. 找不到了
  3. Wikipedia
  4. 玩個機吧

頭圖來自:KeyCDN

採用 CC BY-NC-SA 4.0 協議進行許可
上次改過於 2026 年 3 月 17 日 09:14 UTC