前言
主要記錄 https 加速的優化手段。
李柱明博客:https://www.cnblogs.com/lizhuming/p/15486943.html
HTTPS 的連接很慢
https 步驟簡要划分
HTTPS 連接大致分為兩個部分:
- 非對稱加密握手(TLS 握手);
- 對稱加密報文傳輸。
平時說的 HTTPS 很慢是前面第一部分,非對稱加密握手階段很慢。
而握手成功后是很快的。
握手耗時
TLS 握手最長可以花費兩個消息往返(2-RTT)。
除了在握手消息的網絡耗時之外,還有:
- 產生用於密鑰交換的臨時公私鑰對(ECDHE);
- 驗證證書時訪問 CA 獲取 CRL 或者 OCSP;(這兩個知識點可以看后面)
- 非對稱加密解密處理“Pre-Master”。
不做優化的情況下,HTTPS 建立連接可能會比 HTTP 慢上幾百毫秒甚至幾秒。
TLS 握手過程中主要耗時圖參考:
-
優化就按照下圖耗時段進行優化。
-
證書驗證
本點只是做理解記錄,如果對 CRL 和 OCSP 有所理解,可以跳過。
CRL
CRL(Certificate revocation list)即是證書吊銷列表。
由 CA 定期發布,里面是所有被撤銷信任的證書序號。
查其內容即可知道本證書是否失效。
缺點:
- CRL 是定期發布,如果證書失效了,但是 CA 機構還沒有及時更新 CRL,會導致誤判的安全隱患。
- 隨着吊銷的證書越來越多,下載的 CRL 就會越來越大了,檢索也越來越耗時。簡直就是越來越浪費空間浪費時間。
所以現在用 OCSP 取代 CRL。
OCSP
OCSP(Online Certificate Status Protocol)在線證書狀態協議。
客戶端將請求發到一個 OCSP 應答器(服務器),應答器建立與 CA 證書庫鏈接查詢該證書的狀態,然后回復“ 有效 ”、“ 注銷 ”或“ 未知 ”的響應。
優點:
- 在線驗證比 CRL 處理速度更快、更方便,也更具獨立性。
- 並避免了令人頭痛的邏輯問題和處理開銷。
問題&解決:
-
OCSP 也要多出一次網絡請求的消耗,而且還依賴於 CA 服務器,如果 CA 服務器很忙,也是很耗時的。
- 解決:OCSP Stapling:OCSP 裝訂,是一個補丁。可以讓服務器預先訪問 CA 獲取 OCSP 響應,然后在握手時隨着證書一起發給客戶端,免去了客戶端連接 CA 服務器查詢的時間。
硬件優化
HTTPS 連接是計算密集型,而不是 I/O 密集型:
- 計算密集型解決方法:加速計算。升級 CPU,硬件加速卡等等。
- I/O 密集型解決方法:升級網卡、帶寬、SSD 存儲等等數據通信設備。
HTTPS 連接是計算密集型,而不是 I/O 密集型,其硬件優化手段有:
- 升級 CPU:如果內建 AES 優化,可以加速握手,也可以加速傳輸。
- SSL 加速卡:加解密時調用它的 API,讓專門的硬件來做非對稱加解密,分擔 CPU 的計算壓力。
- SSL 加速服務器:用專門的服務器集群解決 TLS 握手時的加密解密計算,性能要比單純的“加速卡”要強大。
軟件優化
軟件方面的優化還可以再分成兩部分:一個是 軟件升級 ,一個是 協議優化 。
軟件升級
軟件升級,如升級 linux 內核,升級 OpenSSL 等等。
這些軟件在更新版本的時候都會做性能優化、修復錯誤,只要運維能夠主動配合,這種軟件優化是最容易做的,也是最容易達成優化效果的。
但是升級內核兼容性要解決,版本跨度大,升級也是很棘手的。
協議優化
-
目前盡量采用 TLS1.3。
- 它大幅度簡化了握手的過程,完全握手只要 1-RTT,而且更加安全。
-
握手時使用的密鑰交換協議盡量選用橢圓曲線的 ECDHE 算法。(RSA 在 TLS 1.3 中已經被廢棄)
- 運算速度快。
- 安全性高。
- 支持“False Start”,能夠把 TLS1.2 握手的消息往返由 2-RTT 減少到 1-RTT,達到與 TLS1.3 類似的效果。
-
橢圓曲線也要選擇高性能的曲線。
- 最好是 x25519,次優選擇是 P-256。
-
對稱加密算法方面,可以選用“AES_128_GCM”,比“AES_256_GCM”略快一點點。
證書優化
握手過程中的證書驗證也是一個比較耗時的操作,服務器需要把自己的證書鏈全發給客戶端,然后客戶端接收后再逐一驗證。
兩個可優化點:
-
證書傳輸。
-
證書驗證。
-
服務器的證書可以選擇橢圓曲線(ECDSA)證書而不是 RSA 證書。
- 因為 224 位的 ECC 相當於 2048 位的 RSA。證書小,傳輸就少,計算也少。
-
采用 OCSP 驗證證書。開啟 OCSP Stapling。
會話復用
大殺器。
連接同一服務器時,明明證書、公鑰都一樣,但是每次通信都需要重新 TLS 握手,重新驗證證書來獲取公鑰,算出對稱秘鑰。
這樣太浪費時間了,我們可以使用緩存功能,雙方把會話 ID 和對稱秘鑰記錄下來,下次鏈接時直接使用豈不是更加方便快捷嗎,其實這就是會話復用。
會話復用(TLS session resumption),復用分兩種:
-
Session ID:客戶端和服務器首次連接后各自保存一個會話的 ID 號,內存里存儲主密鑰和其他相關的信息。
- 當客戶端再次連接時發一個 ID 過來,服務器就在內存里找,找到就直接用主密鑰恢復會話狀態,跳過證書驗證和密鑰交換,只用一個消息往返就可以建立安全通信。
- 缺點:服務器保存每一個客戶端的會話數據,對於擁有百萬、千萬級別用戶的網站來說存儲量就成了大問題,加重了服務器的負擔。
-
Session Ticket:會話票證。下述。
Session ID:
會話票證
由於 Session ID 方案加重了服務器負擔,所以出現了另一種方案,Session Ticket(會話票證)。
Session Ticket:會話票證。
- 存儲的責任由服務器轉移到客戶端,即是服務器會對會話記錄進行加密(如對稱主秘鑰、加密算法等等)得到的 Ticket ,然后用 New Session Ticket 消息發給客戶端,讓客戶端保存。
- 重連的時候,客戶端使用擴展 session_ticket 發送 Ticket 而不是 Session ID,服務器解密后驗證有效期,就可以恢復會話,開始加密通信。
- 不過 Session Ticket 方案需要使用一個固定的密鑰文件(ticket_key)來加密 Ticket,為了防止密鑰被破解,保證“前向安全”,密鑰文件需要定期輪換。
預共享密鑰
Pre-shared Key,簡稱為“PSK”,預共享密鑰。
False Start、Session ID、Session Ticket 等方式只能實現 1-RTT,而 TLS1.3 的 PSK 更進一步實現了 0-RTT。
原理和 Session Ticket 差不多,但在發送 Ticket 的同時會帶上應用數據(Early Data),免去了服務器確認步驟。
注意:
-
PSK 也不是完美的,它為了追求效率而犧牲了一點安全性,容易受到 重放攻擊(Replay attack)的威脅。黑客可以截獲 PSK 的數據,像復讀機那樣反復向服務器發送。
- 解決:在消息里加入時間戳、nonce 驗證,或者 一次性票證 限制重放。