基於協議和配置的優化html
上文講到 HTTPS 對用戶訪問速度的影響。linux
本文就爲你們介紹 HTTPS 在訪問速度,計算性能,安全等方面基於協議和配置的優化。nginx
HTTPS 和 HTTP 使用 TCP 協議進行傳輸,也就意味着必須經過三次握手創建 TCP 鏈接,web
但一個 RTT 的時間內只傳輸一個 syn 包是否是太浪費?算法
能不能在 syn 包發出的同時捎上應用層的數據?chrome
實際上是能夠的,這也是 tcp fast open 的思路,簡稱 TFO。具體原理能夠參考 rfc7413。apache
遺憾的是 TFO 須要高版本內核的支持,linux 從 3.7 之後支持 TFO,可是目前的 windows 系統還不支持 TFO,因此只能在公司內部服務器之間發揮做用。swift
前面提到過將用戶 HTTP 請求 302 跳轉到 HTTPS,這會有兩個影響:windows
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。
(不須要服務器告訴 瀏覽器 www.baidu.com 要跳轉到 302 這個步驟了, 瀏覽器看到輸入了http 直接轉換成 https )
Chrome, firefox, ie 都支持了 HSTS(http://caniuse.com/#feat=stricttransportsecurity)。
Session resume 顧名思義就是複用 session,實現簡化握手。複用 session 的好處有兩個:
1, 減小了 CPU 消耗,由於後續的訪問不須要進行非對稱密鑰交換的計算 ?。
2, 提高訪問速度,不須要進行徹底握手階段二,節省了一個(tls) RTT 和計算耗時。
TLS 協議目前提供兩種機制實現 session resume,分別介紹一下。
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,可以明顯提高用戶的訪問速度,節省服務器計算資源。
上節提到了 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。
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 的指令就能開啓這個功能:
ssl_stapling on;ssl_stapling_file ocsp.staple; |
一般狀況下,應用層數據必須等徹底握手所有結束以後才能傳輸。這個其實比較浪費時間,那能不能相似 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。
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 協議。
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 位長度的安全強度。在進行相同的模指數運算時速度顯然要快不少。
通常來說,新版的 openssl 相比老版的計算速度和安全性都會有提高。好比 openssl1.0.2 採用了 intel 最新的優化成果,橢圓曲線 p256 的計算性能提高了 4 倍。(https://eprint.iacr.org/2013/816.pdf)
Openssl 2014 年就升級了 5 次,基本都是爲了修復實現上的 BUG 或者算法上的漏洞而升級的。因此儘可能使用最新版本,避免安全上的風險。
如今比較經常使用的 TLS 硬件加速方案主要有兩種:
1, SSL 專用加速卡。
2, GPU SSL 加速。
上述兩個方案的主流用法都是將硬件插入到服務器的 PCI 插槽中,由硬件完成最消耗性能的計算。但這樣的方案有以下缺點:
1, 支持算法有限。好比不支持 ECC,不支持 GCM 等。
2, 升級成本高。
a) 出現新的加密算法或者協議時,硬件加速方案沒法及時升級。
b) 出現比較大的安全漏洞時,部分硬件方案在沒法在短時間內升級解決。好比 2014 年暴露的 heartbleed 漏洞。
3, 沒法充分利用硬件加速性能。硬件加速程序通常都運行在內核態,計算結果傳遞到應用層須要 IO 和內存拷貝開銷,即便硬件計算性能很是好,上層的同步等待和 IO 開銷也會致使總體性能達不到預期,沒法充分利用硬件加速卡的計算能力。
4, 維護性差。硬件驅動及應用層 API 大部分是由安全廠家提供,出現問題後還須要廠家跟進。用戶沒法掌握核心代碼,比較被動。不像開源的 openssl,無論算法仍是協議,用戶都能掌握。
也正是由於上述緣由,百度實現了專用的 SSL 硬件加速集羣。基本思路是:
1, 優化 TLS 協議棧,剝離最消耗 CPU 資源的計算,主要有以下部分:
a) RSA 中的加解密計算。
b) ECC 算法中的公私鑰生成。
c) ECC 算法中的共享密鑰生成。
2, 優化硬件計算部分。硬件計算不涉及協議及狀態交互,只須要處理大數運算。
3, Web server 到 TLS 計算集羣之間的任務是異步的。即 web server 將待計算內容發送給加速集羣后,依然能夠繼續處理其餘請求,整個過程是異步非阻塞的。
SSL2.0 早就被證實是不安全的協議了,統計發現目前已經沒有客戶端支持 SSL2.0,因此能夠放心地在服務端禁用 SSL2.0 協議。
2014 年爆發了 POODLE 攻擊,SSL3.0 所以被證實是不安全的。可是統計發現依然有 0.5% 的流量只支持 SSL3.0。因此只能有選擇地支持 SSL3.0。
TLS1.1 及 1.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 以上的安全哈希函數。
降級攻擊通常包括兩種:加密套件降級攻擊 (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,就不會接受比服務端最高協議版本低的協議。
從新協商(tls renegotiation)分爲兩種:
加密套件重協商 (cipher suite renegotiation) 和協議重協商(protocol renegotiation)。
從新協商會有兩個隱患:
1, 重協商後使用弱的安全算法。這樣的後果就是傳輸內容很容易泄露。
2, 重協商過程當中不斷髮起徹底握手請求,觸發服務端進行高強度計算並引起服務拒絕。
對於重協商,最直接的保護手段就是禁止客戶端主動重協商,固然出於特殊場景的需求,應該容許服務端主動發起重協商。
HTTPS 的實踐和優化涉及到了很是多的知識點,因爲篇幅關係,本文對不少優化策略只是簡單介紹了一下.
若是想要了解協議背後的原理,仍是須要詳細閱讀 TLS 協議及 PKI 知識。對於大型站點來講,若是但願作到極致,
HTTPS 的部署須要結合產品和基礎設施的架構來進行詳細的考慮,比起部署支持 HTTPS 的接入和對它的優化,
在產品和運維層面上花費的功夫會更多。本系列的下一篇文章將進一步進行介紹。