大型網站的 HTTPS 實踐(3):基於協議和配置的優化

發表於2015-05-05

1 前言

上文講到 HTTPS 對使用者訪問速度的影響。

本文就為大家介紹 HTTPS 在訪問速度,計算效能,安全等方面基於協議和配置的優化。

2 HTTPS 訪問速度優化

2.1 Tcp fast open

HTTPS 和 HTTP 使用 TCP 協議進行傳輸,也就意味著必須通過三次握手建立 TCP 連線,但一個 RTT 的時間內只傳輸一個 syn 包是不是太浪費?能不能在 syn 包發出的同時捎上應用層的資料?其實是可以的,這也是 tcp fast open 的思路,簡稱 TFO。具體原理可以參考 rfc7413。

遺憾的是 TFO 需要高版本核心的支援,linux 從 3.7 以後支援 TFO,但是目前的 windows 系統還不支援 TFO,所以只能在公司內部伺服器之間發揮作用。

2.2 HSTS

前面提到過將使用者 HTTP 請求 302 跳轉到 HTTPS,這會有兩個影響:

1,    不安全,302 跳轉不僅暴露了使用者的訪問站點,也很容易被中間者支援。

2,    降低訪問速度,302 跳轉不僅需要一個 RTT,瀏覽器執行跳轉也需要執行時間。

由於 302 跳轉事實上是由瀏覽器觸發的,伺服器無法完全控制,這個需求導致了 HSTS 的誕生:

HSTS(HTTP Strict Transport Security)。服務端返回一個 HSTS 的 http header,瀏覽器獲取到 HSTS 頭部之後,在一段時間內,不管使用者輸入www.baidu.com還是http://www.baidu.com,都會預設將請求內部跳轉成https://www.baidu.com

Chrome, firefox, ie 都支援了 HSTS(http://caniuse.com/#feat=stricttransportsecurity)。

2.3 Session resume

Session resume 顧名思義就是複用 session,實現簡化握手。複用 session 的好處有兩個:

1,    減少了 CPU 消耗,因為不需要進行非對稱金鑰交換的計算。

2,    提升訪問速度,不需要進行完全握手階段二,節省了一個 RTT 和計算耗時。

TLS 協議目前提供兩種機制實現 session resume,分別介紹一下。

2.3.1 Session cache

Session cache 的原理是使用 client hello 中的 session id 查詢服務端的 session cache, 如果服務端有對應的快取,則直接使用已有的 session 資訊提前完成握手,稱為簡化握手。

Session cache 有兩個缺點:

1,    需要消耗服務端記憶體來儲存 session 內容。

2,    目前的開源軟體包括 nginx,apache 只支援單機多程式間共享快取,不支援多機間分散式快取,對於百度或者其他大型網際網路公司而言,單機 session cache 幾乎沒有作用。

Session cache 也有一個非常大的優點:

1,   session id 是 TLS 協議的標準欄位,市面上的瀏覽器全部都支援 session cache。

百度通過對 TLS 握手協議及伺服器端實現的優化,已經支援全域性的 session cache,能夠明顯提升使用者的訪問速度,節省伺服器計算資源。

2.3.2 Session ticket

上節提到了 session cache 的兩個缺點,session ticket 能夠彌補這些不足。

Session ticket 的原理參考 RFC4507。簡述如下:

server 將 session 資訊加密成 ticket 傳送給瀏覽器,瀏覽器後續握手請求時會傳送 ticket,server 端如果能成功解密和處理 ticket,就能完成簡化握手。

顯然,session ticket 的優點是不需要服務端消耗大量資源來儲存 session 內容。

Session ticket 的缺點:

1,    session ticket 只是 TLS 協議的一個擴充套件特性,目前的支援率不是很廣泛,只有 60% 左右。

2,    session ticket 需要維護一個全域性的 key 來加解密,需要考慮 KEY 的安全性和部署效率。

總體來講,session ticket 的功能特性明顯優於 session cache。希望客戶端實現優先支援 session ticket。

2.4 Ocsp stapling

Ocsp 全稱線上證書狀態檢查協議 (rfc6960),用來向 CA 站點查詢證書狀態,比如是否撤銷。通常情況下,瀏覽器使用 OCSP 協議發起查詢請求,CA 返回證書狀態內容,然後瀏覽器接受證書是否可信的狀態。

這個過程非常消耗時間,因為 CA 站點有可能在國外,網路不穩定,RTT 也比較大。那有沒有辦法不直接向 CA 站點請求 OCSP 內容呢?ocsp stapling 就能實現這個功能。

詳細介紹參考 RFC6066 第 8 節。簡述原理就是瀏覽器發起 client hello 時會攜帶一個 certificate status request 的擴充套件,服務端看到這個擴充套件後將 OCSP 內容直接返回給瀏覽器,完成證書狀態檢查。

由於瀏覽器不需要直接向 CA 站點查詢證書狀態,這個功能對訪問速度的提升非常明顯。

Nginx 目前已經支援這個 ocsp stapling file,只需要配置 ocsp stapling file 的指令就能開啟這個功能:

2.5 False start

通常情況下,應用層資料必須等完全握手全部結束之後才能傳輸。這個其實比較浪費時間,那能不能類似 TFO 一樣,在完全握手的第二個階段將應用資料一起發出來呢?google 提出了 false start 來實現這個功能。詳細介紹參考https://tools.ietf.org/html/draft-bmoeller-tls-falsestart-00

簡單概括 False start 的原理就是在 client_key_exchange 發出時將應用層資料一起發出來,能夠節省一個 RTT。

False start 依賴於 PFS(perfect forward secrecy 完美前向加密),而 PFS 又依賴於 DHE 金鑰交換系列演算法(DHE_RSA, ECDHE_RSA, DHE_DSS, ECDHE_ECDSA),所以儘量優先支援 ECDHE 金鑰交換演算法實現 false start。

2.6 使用 SPDY 或者 HTTP2

SPDY 是 google 推出的優化 HTTP 傳輸效率的協議(https://www.chromium.org/spdy),它基本上沿用了 HTTP 協議的語義, 但是通過使用幀控制實現了多個特性,顯著提升了 HTTP 協議的傳輸效率。

SPDY 最大的特性就是多路複用,能將多個 HTTP 請求在同一個連線上一起發出去,不像目前的 HTTP 協議一樣,只能序列地逐個傳送請求。Pipeline 雖然支援多個請求一起傳送,但是接收時依然得按照順序接收,本質上無法解決併發的問題。

HTTP2 是 IETF 2015 年 2 月份通過的 HTTP 下一代協議,它以 SPDY 為原型,經過兩年多的討論和完善最終確定。

本文就不過多介紹 SPDY 和 HTTP2 的收益,需要說明兩點:

1,    SPDY 和 HTTP2 目前的實現預設使用 HTTPS 協議。

2,    SPDY 和 HTTP2 都支援現有的 HTTP 語義和 API,對 WEB 應用幾乎是透明的。

Google 宣佈 chrome 瀏覽器 2016 年將放棄 SPDY 協議,全面支援 HTTP2,但是目前國內部分瀏覽器廠商進度非常慢,不僅不支援 HTTP2,連 SPDY 都沒有支援過。

百度服務端和百度手機瀏覽器現在都已經支援 SPDY3.1 協議。

 

3 HTTPS 計算效能優化

3.1 優先使用 ECC

ECC 橢圓加密算術相比普通的離散對數計算速度效能要強很多。下表是 NIST 推薦的金鑰長度對照表。

對稱金鑰大小 RSA 和 DH 金鑰大小 ECC 金鑰大小
80 1024 160
112 2048 224
128 3072 256
192 7680 384
256 15360 521

表格 2 NIST 推薦使用的金鑰長度

對於 RSA 演算法來講,目前至少使用 2048 位以上的金鑰長度才能保證安全性。ECC 只需要使用 224 位長度的金鑰就能實現 RSA2048 位長度的安全強度。在進行相同的模指數運算時速度顯然要快很多。

3.2 使用最新版的 openssl

一般來講,新版的 openssl 相比老版的計算速度和安全性都會有提升。比如 openssl1.0.2 採用了 intel 最新的優化成果,橢圓曲線 p256 的計算效能提升了 4 倍。(https://eprint.iacr.org/2013/816.pdf)

Openssl 2014 年就升級了 5 次,基本都是為了修復實現上的 BUG 或者演算法上的漏洞而升級的。所以儘量使用最新版本,避免安全上的風險。

3.3 硬體加速方案

現在比較常用的 TLS 硬體加速方案主要有兩種:

1,    SSL 專用加速卡。

2,    GPU SSL 加速。

上述兩個方案的主流用法都是將硬體插入到伺服器的 PCI 插槽中,由硬體完成最消耗效能的計算。但這樣的方案有如下缺點:

1,    支援演算法有限。比如不支援 ECC,不支援 GCM 等。

2,    升級成本高。

a)       出現新的加密演算法或者協議時,硬體加速方案無法及時升級。

b)      出現比較大的安全漏洞時,部分硬體方案在無法在短期內升級解決。比如 2014 年暴露的 heartbleed 漏洞。

3,    無法充分利用硬體加速效能。硬體加速程式一般都執行在核心態,計算結果傳遞到應用層需要 IO 和記憶體拷貝開銷,即使硬體計算效能非常好,上層的同步等待和 IO 開銷也會導致整體效能達不到預期,無法充分利用硬體加速卡的計算能力。

4,    維護性差。硬體驅動及應用層 API 大部分是由安全廠家提供,出現問題後還需要廠家跟進。使用者無法掌握核心程式碼,比較被動。不像開源的 openssl,不管演算法還是協議,使用者都能掌握。

3.4 TLS 遠端代理計算

也正是因為上述原因,百度實現了專用的 SSL 硬體加速叢集。基本思路是:

1,    優化 TLS 協議棧,剝離最消耗 CPU 資源的計算,主要有如下部分:

a)       RSA 中的加解密計算。

b)      ECC 演算法中的公私鑰生成。

c)       ECC 演算法中的共享金鑰生成。

2,    優化硬體計算部分。硬體計算不涉及協議及狀態互動,只需要處理大數運算。

3,    Web server 到 TLS 計算叢集之間的任務是非同步的。即 web server 將待計算內容傳送給加速叢集后,依然可以繼續處理其他請求,整個過程是非同步非阻塞的。

4 HTTPS 安全配置

4.1 協議版本選擇

SSL2.0 早就被證明是不安全的協議了,統計發現目前已經沒有客戶端支援 SSL2.0,所以可以放心地在服務端禁用 SSL2.0 協議。

2014 年爆發了 POODLE 攻擊,SSL3.0 因此被證明是不安全的。但是統計發現依然有 0.5% 的流量只支援 SSL3.0。所以只能有選擇地支援 SSL3.0。

TLS1.1 及 1.2 目前為止沒有發現安全漏洞,建議優先支援。

4.2 加密套件選擇

加密套件包含四個部分:

1,    非對稱金鑰交換演算法。建議優先使用 ECDHE,禁用 DHE,次優先選擇 RSA。

2,    證書籤名演算法。由於部分瀏覽器及作業系統不支援 ECDSA 簽名,目前預設都是使用 RSA 簽名,其中 SHA1 簽名已經不再安全,chrome 及微軟 2016 年開始不再支援 SHA1 簽名的證書 (http://googleonlinesecurity.blogspot.jp/2014/09/gradually-sunsetting-sha-1.html)。

3,    對稱加解密演算法。優先使用 AES-GCM 演算法,針對 1.0 以上協議禁用 RC4( rfc7465)。

4,    內容一致性校驗演算法。Md5 和 sha1 都已經不安全,建議使用 sha2 以上的安全雜湊函式。

4.3 HTTPS 防攻擊

4.3.1 防止協議降級攻擊

降級攻擊一般包括兩種:加密套件降級攻擊 (cipher suite rollback) 和協議降級攻擊(version roll back)。降級攻擊的原理就是攻擊者偽造或者修改 client hello 訊息,使得客戶端和伺服器之間使用比較弱的加密套件或者協議完成通訊。

為了應對降級攻擊,現在 server 端和瀏覽器之間都實現了 SCSV 功能,原理參考https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00

一句話解釋就是如果客戶端想要降級,必須傳送 TLS_SCSV 的訊號,伺服器如果看到 TLS_SCSV,就不會接受比服務端最高協議版本低的協議。

4.3.2 防止重新協商攻擊

重新協商(tls renegotiation)分為兩種:加密套件重協商 (cipher suite renegotiation) 和協議重協商(protocol renegotiation)。

重新協商會有兩個隱患:

1,      重協商後使用弱的安全演算法。這樣的後果就是傳輸內容很容易洩露。

2,      重協商過程中不斷髮起完全握手請求,觸發服務端進行高強度計算並引發服務拒絕。

對於重協商,最直接的保護手段就是禁止客戶端主動重協商,當然出於特殊場景的需求,應該允許服務端主動發起重協商。

5 結束語

HTTPS 的實踐和優化涉及到了非常多的知識點,由於篇幅關係,本文對很多優化策略只是簡單介紹了一下. 如果想要了解協議背後的原理,還是需要詳細閱讀 TLS 協議及 PKI 知識。對於大型站點來說,如果希望做到極致,HTTPS 的部署需要結合產品和基礎設施的架構來進行詳細的考慮,比起部署支援 HTTPS 的接入和對它的優化,在產品和運維層面上花費的功夫會更多。本系列的下一篇文章將進一步進行介紹。

相關文章