大型網站的 HTTPS 實踐

百度在2015年即完成HTTPS改造,那大型網站的HTTPS改造中都有哪些實踐經驗,學院君特分析這篇干貨滿滿系列內容,轉自百度運維博客。

百度已經于近日上線了全站 HTTPS 的安全搜索,默認會將 HTTP 請求跳轉成 HTTPS。本文重點介紹 HTTPS 協議, 并簡單介紹部署全站 HTTPS 的意義。

國外的大型互聯網公司很多已經啟用了全站 HTTPS,這也是未來互聯網的趨勢。國內的大型互聯網并沒有全站部署 HTTPS,只是在一些涉及賬戶或者交易的子頁面 / 子請求上啟用了 HTTPS。百度搜索首次全站部署 HTTPS,對國內互聯網的全站 HTTPS 進程必將有著巨大的推動作用。

目前互聯網上關于 HTTPS 的中文資料比較少,本文就著重介紹了 HTTPS 協議涉及到的重要知識點和平時不太容易理解的盲區,希望能對大家理解 HTTPS 協議有幫助。百度 HTTPS 性能優化涉及到大量內容,從前端頁面、后端架構、協議特性、加密算法、流量調度、架構和運維、安全等方面都做了大量工作。本系列的文章將一一進行介紹。


大型網站的 HTTPS 實踐(1):HTTPS 協議和原理

1、HTTPS 協議概述

HTTPS 可以認為是 HTTP + TLS。HTTP 協議大家耳熟能詳了,目前大部分 WEB 應用和網站都是使用 HTTP 協議傳輸的。

TLS 是傳輸層加密協議,它的前身是 SSL 協議,最早由 netscape 公司于 1995 年發布,1999 年經過 IETF 討論和規范后,改名為 TLS。如果沒有特別說明,SSL 和 TLS 說的都是同一個協議。

HTTP 和 TLS 在協議層的位置以及 TLS 協議的組成如下圖:


圖 1 TLS 協議格式

TLS 協議主要有五部分:應用數據層協議,握手協議,報警協議,加密消息確認協議,心跳協議。

TLS 協議本身又是由 record 協議傳輸的,record 協議的格式如上圖最右所示。

目前常用的 HTTP 協議是 HTTP1.1,常用的 TLS 協議版本有如下幾個:TLS1.2, TLS1.1, TLS1.0 和 SSL3.0。其中 SSL3.0 由于 POODLE 攻擊已經被證明不安全,但統計發現依然有不到 1% 的瀏覽器使用 SSL3.0。TLS1.0 也存在部分安全漏洞,比如 RC4 和 BEAST 攻擊。

TLS1.2 和 TLS1.1 暫時沒有已知的安全漏洞,比較安全,同時有大量擴展提升速度和性能,推薦大家使用。

需要關注一點的就是 TLS1.3 將會是 TLS 協議一個非常重大的改革。不管是安全性還是用戶訪問速度都會有質的提升。不過目前沒有明確的發布時間。

同時 HTTP2 也已經正式定稿,這個由 SPDY 協議演化而來的協議相比 HTTP1.1 又是一個非常重大的變動,能夠明顯提升應用層數據的傳輸效率。

2、HTTPS 功能介紹

百度使用 HTTPS 協議主要是為了保護用戶隱私,防止流量劫持。

HTTP 本身是明文傳輸的,沒有經過任何安全處理。例如用戶在百度搜索了一個關鍵字,比如“蘋果手機”,中間者完全能夠查看到這個信息,并且有可能打電話過來騷擾用戶。也有一些用戶投訴使用百度時,發現首頁或者結果頁面浮了一個很長很大的廣告,這也肯定是中間者往頁面插的廣告內容。如果劫持技術比較低劣的話,用戶甚至無法訪問百度。

這里提到的中間者主要指一些網絡節點,是用戶數據在瀏覽器和百度服務器中間傳輸必須要經過的節點。比如 WIFI 熱點,路由器,防火墻,反向代理,緩存服務器等。

在 HTTP 協議下,中間者可以隨意嗅探用戶搜索內容,竊取隱私甚至篡改網頁。不過 HTTPS 是這些劫持行為的克星,能夠完全有效地防御。

總體來說,HTTPS 協議提供了三個強大的功能來對抗上述的劫持行為:

1、內容加密。瀏覽器到百度服務器的內容都是以加密形式傳輸,中間者無法直接查看原始內容。

2、身份認證。保證用戶訪問的是百度服務,即使被 DNS 劫持到了第三方站點,也會提醒用戶沒有訪問百度服務,有可能被劫持

3、數據完整性。防止內容被第三方冒充或者篡改。

那 HTTPS 是如何做到上述三點的呢?下面從原理角度介紹一下。

3、HTTPS 原理介紹

3.1 內容加密

加密算法一般分為兩種,對稱加密和非對稱加密。所謂對稱加密(也叫密鑰加密)就是指加密和解密使用的是相同的密鑰。而非對稱加密(也叫公鑰加密)就是指加密和解密使用了不同的密鑰。



對稱內容加密強度非常高,一般破解不了。但存在一個很大的問題就是無法安全地生成和保管密鑰。假如客戶端軟件和服務器之間每次會話都使用固定的,相同的密鑰加密和解密,肯定存在很大的安全隱患。如果有人從客戶端端獲取到了對稱密鑰,整個內容就不存在安全性了,而且管理海量的客戶端密鑰也是一件很復雜的事情。

非對稱加密主要用于密鑰交換(也叫密鑰協商),能夠很好地解決這個問題。瀏覽器和服務器每次新建會話時都使用非對稱密鑰交換算法協商出對稱密鑰,使用這些對稱密鑰完成應用數據的加解密和驗證,整個會話過程中的密鑰只在內存中生成和保存,而且每個會話的對稱密鑰都不相同(除非會話復用),中間者無法竊取。

非對稱密鑰交換很安全,但同時也是 HTTPS 性能和速度嚴重降低的“罪魁禍首”。想要知道 HTTPS 為什么影響速度,為什么消耗資源,就一定要理解非對稱密鑰交換的整個過程。

下面重點介紹一下非對稱密鑰交換的數學原理及在 TLS 握手過程中的應用。

3.1.1 非對稱密鑰交換

在非對稱密鑰交換算法出現以前,對稱加密一個很大的問題就是不知道如何安全生成和保管密鑰。非對稱密鑰交換過程主要就是為了解決這個問題,使得對稱密鑰的生成和使用更加安全。

密鑰交換算法本身非常復雜,密鑰交換過程涉及到隨機數生成,模指數運算,空白補齊,加密,簽名等操作。

常見的密鑰交換算法有 RSA,ECDHE,DH,DHE 等算法。它們的特性如下:

RSA:算法實現簡單,誕生于 1977 年,歷史悠久,經過了長時間的破解測試,安全性高。缺點就是需要比較大的素數(目前常用的是 2048 位)來保證安全強度,很消耗 CPU 運算資源。RSA 是目前唯一一個既能用于密鑰交換又能用于證書簽名的算法。

DH:diffie-hellman 密鑰交換算法,誕生時間比較早(1977 年),但是 1999 年才公開。缺點是比較消耗 CPU 性能。

ECDHE:使用橢圓曲線(ECC)的 DH 算法,優點是能用較小的素數(256 位)實現 RSA 相同的安全等級。缺點是算法實現復雜,用于密鑰交換的歷史不長,沒有經過長時間的安全攻擊測試。

ECDH:不支持 PFS,安全性低,同時無法實現 false start。

DHE:不支持 ECC。非常消耗 CPU 資源。

建議優先支持 RSA 和 ECDH_RSA 密鑰交換算法。原因是:

1、ECDHE 支持 ECC 加速,計算速度更快。支持 PFS,更加安全。支持 false start,用戶訪問速度更快。

2、目前還有至少 20% 以上的客戶端不支持 ECDHE,我們推薦使用 RSA 而不是 DH 或者 DHE,因為 DH 系列算法非常消耗 CPU(相當于要做兩次 RSA 計算)。



需要注意通常所說的 ECDHE 密鑰交換默認都是指 ECDHE_RSA,使用 ECDHE 生成 DH 算法所需的公私鑰,然后使用 RSA 算法進行簽名最后再計算得出對稱密鑰。

非對稱加密相比對稱加密更加安全,但也存在兩個明顯缺點:

1、CPU 計算資源消耗非常大。一次完全 TLS 握手,密鑰交換時的非對稱解密計算量占整個握手過程的 90% 以上。而對稱加密的計算量只相當于非對稱加密的 0.1%,如果應用層數據也使用非對稱加解密,性能開銷太大,無法承受。

2、非對稱加密算法對加密內容的長度有限制,不能超過公鑰長度。比如現在常用的公鑰長度是 2048 位,意味著待加密內容不能超過 256 個字節。

所以公鑰加密目前只能用來作密鑰交換或者內容簽名,不適合用來做應用層傳輸內容的加解密。

非對稱密鑰交換算法是整個 HTTPS 得以安全的基石,充分理解非對稱密鑰交換算法是理解 HTTPS 協議和功能的關鍵。

下面分別通俗地介紹一下 RSA 和 ECDHE 在密鑰交換過程中的應用。

3.1.1.1 RSA 密鑰協商

3.1.1.1.1 RSA 算法介紹

RSA 算法的安全性是建立在乘法不可逆或者大數因子很難分解的基礎上。RSA 的推導和實現涉及到了歐拉函數和費馬定理及模反元素的概念,有興趣的讀者可以自行百度。

RSA 算法是統治世界的最重要算法之一,而且從目前來看,RSA 也是 HTTPS 體系中最重要的算法,沒有之一。

RSA 的計算步驟如下:

1、隨機挑選兩個質數 p, q,假設 p = 13, q = 19。 n = p * q = 13 * 19 = 247;

2、?(n) 表示與整數 n 互質數的個數。如果 n 等于兩個質數的積,則?(n)=(p-1)(q-1) 挑選一個數 e,滿足 1< e <?(n) 并且 e 與互質,假設 e = 17;

3、計算 e 關于 n 的模反元素, ed=1 mod ?(n) , 由 e = 17 ,?(n) =216  可得 d = 89;

4、求出了 e,和 d,假設明文 m = 135,密文用 c 表示。那么加解密計算如下:


實際應用中,(n,e) 組成了公鑰對,(n,d)組成了私鑰對,其中 n 和 d 都是一個接近 22048的大數。即使現在性能很強的 CPU,想要計算 m≡c^d mod(n),也需要消耗比較大的計算資源和時間。

公鑰對 (n, e) 一般都注冊到了證書里,任何人都能直接查看,比如百度證書的公鑰對如下圖,其中最末 6 個數字(010001)換算成 10 進制就是 65537,也就是公鑰對中的 e。e 取值比較小的好處有兩個:

1、由 c=m^e mod(n) 可知,e 較小,客戶端 CPU 計算消耗的資源較少。

2、加大 server 端的破解難度。e 比較小,私鑰對中的 d 必然會非常大。所以 d 的取值空間也就非常大,增加了破解難度。

那為什么 (n,e) 能做為公鑰公開,甚至大家都能直接從證書中查看到,這樣安全嗎?分析如下:

由于 ed≡1 mod ?(n),知道了 e 和 n,想要求出私鑰 d,就必須知道?(n)。而?(n)=(p-1)*(q-1),必須計算出 p 和 q 才能確定私鑰 d。但是當 n 大到一定程度時(比如接近 2^2048),即使現在最快的 CPU 也無法進行這個因式分解,即無法知道 n 是由哪個數 p 和 q 乘出來的。所以就算知道了公鑰,整個加解密過程還是非常安全的。


圖 百度 HTTPS 證書公鑰

3.1.1.1.2 握手過程中的 RSA 密鑰協商

介紹完了 RSA 的原理,那最終會話所需要的對稱密鑰是如何生成的呢?跟 RSA 有什么關系?

以 TLS1.2 為例簡單描述一下,省略跟密鑰交換無關的握手消息。過程如下:

1、瀏覽器發送 client_hello,包含一個隨機數 random1。

2、服務端回復 server_hello,包含一個隨機數 random2,同時回復 certificate,攜帶了證書公鑰 P。

3、瀏覽器接收到 random2 之后就能夠生成 premaster_secrect 以及 master_secrect。其中 premaster_secret 長度為 48 個字節,前 2 個字節是協議版本號,剩下的 46 個字節填充一個隨機數。結構如下:


master secrect 的生成算法簡述如下:


而 master secrect 包含了六部分內容,分別是用于校驗內容一致性的密鑰,用于對稱內容加解密的密鑰,以及初始化向量(用于 CBC 模式),客戶端和服務端各一份。從上式可以看出,把 premaster_key 賦值給 secret,”master key”賦值給 label,瀏覽器和服務器端的兩個隨機數做種子就能確定地求出一個 48 位長的隨機數。

至此,瀏覽器側的密鑰已經完成協商。

4、瀏覽器使用證書公鑰 P 將 premaster_secrect 加密后發送給服務器。

5、服務端使用私鑰解密得到 premaster_secrect。又由于服務端之前就收到了隨機數 1,所以服務端根據相同的生成算法,在相同的輸入參數下,求出了相同的 master secrect。

RSA 密鑰協商握手過程圖示如下:


圖 6 RSA 密鑰協商過程

可以看出,密鑰協商過程需要 2 個 RTT,這也是 HTTPS 慢的一個重要原因。而 RSA 發揮的關鍵作用就是對 premaster_secrect 進行了加密和解密。中間者不可能破解 RSA 算法,也就不可能知道 premaster_secrect,從而保證了密鑰協商過程的安全性。

3.1.1.2 ECDHE 密鑰協商

3.1.1.2.1 DH 與 ECC 算法原理

ECDHE 算法實現要復雜很多,主要分為兩部分:diffie-hellman 算法(簡稱為 DH)及 ECC(橢圓曲線算術)。他們的安全性都是建立在離散對數計算很困難的基礎上。

簡單介紹一下 dh 算法的實現,先介紹兩個基本概念:

本原根:如果整數 a 是素數 p 的本原根,則 a, a^2, …, a^(p-1) 在 mod p 下都不相同。

離散對數:對任意整數 b 和素數 p 的本原根 a,存在唯一的指數 i 滿足:

b ≡ a^i mod p (0≤i≤p-1)

則稱 i 是 b 的以 a 為底的模 p 的離散對數。

理解這兩個概念,dh 算法就非常簡單了,示例如下:

假設 client 和 server 需要協商密鑰,p=2579,則本原根 a = 2。

1、Client 選擇隨機數 Kc = 123 做為自己的私鑰,計算 Yc = a^Kc  mod p = 2^123 mod 2579 = 2400,把 Yc 作為公鑰發送給 server。

2、Server 選擇隨機數 Ks = 293 作為私鑰,計算 Ys = a^Ks  mod p = s^293 mod 2579 = 968,把 Ys 作為公鑰發送給 client。

3、Client 計算共享密鑰:secrect =  Ys^Kc mod (p) = 968^123  mod(2579) = 434

4、Server 計算共享密鑰:secrect = Yc^Ks mod(p) =2400^293 mod(2579) =434

上述公式中的 Ys,Yc,P, a, 都是公開信息,可以被中間者查看,只有 Ks,Kc 作為私鑰沒有公開,當私鑰較小時,通過窮舉攻擊能夠計算出共享密鑰,但是當私鑰非常大時,窮舉攻擊肯定是不可行的。

DH 算法有一個比較大的缺陷就是需要提供足夠大的私鑰來保證安全性,所以比較消耗 CPU 計算資源。ECC 橢圓曲線算術能夠很好的解決這個問題,224 位的密鑰長度就能達到 RSA2048 位的安全強度。

ECC 的曲線公式描述的其實不是橢圓,只是跟橢圓曲線周長公式形似才叫橢圓曲線加密算術。ECC 涉及到了有限域、群等近世代數的多個概念,就不做詳細介紹了。

ECC 安全性依賴于這樣一個事實:


上式看起來非常簡單,但有如下約束條件:

1、Q 是一個非常大的質數,p, k, q 都是橢圓曲線有限域上的離散點。

2、有限域定義了自己的加法和乘法法則,即使 kQ 的運算也非常復雜。

ECC 應用于 Diffie-Hellman 密鑰交換過程如下:

1、定義一個滿足橢圓方程的有限域,即挑選 p, a, b 滿足如下方程:


2、挑選基點 G = (x, y),G 的階為 n。n 為滿足 nG = 0 的最小正整數。

3、Client 選擇私鑰 Kc (0 <Kc<n ),產生公鑰 Yc =Kc *G

4、server 選擇私鑰 Ks 并產生公鑰 Ys =Ks*G

5、client 計算共享密鑰 K = Kc*Ys   ,server 端計算共享密鑰 Ks*Yc ,這兩者的結果是一樣的,因為:

由上面描述可知,只要確定 p, a, b 就能確定一條有限域上的橢圓曲線,由于不是所有的橢圓曲線都能夠用于加密,所以 p, a, b 的選取非常講究,直接關系曲線的安全性和計算速度。

Openssl 實現的,也是 FIPS 推薦的 256 位素數域上的橢圓曲線參數定義如下:



4.1.1.2.2 握手過程中的 ECDHE 密鑰協商

簡單介紹了 ECC 和 DH 算法的數學原理,我們看下 ECDHE 在 TLS 握手過程中的應用。

相比 RSA,ECDHE 需要多發送一個 server_key_exchange 的握手消息才能完成密鑰協商。

同樣以 TLS1.2 為例,簡單描述一下過程:

1、瀏覽器發送 client_hello,包含一個隨機數 random1,同時需要有 2 個擴展:

a)Elliptic_curves:客戶端支持的曲線類型和有限域參數?,F在使用最多的是 256 位的素數域,參數定義如上節所述。

b)Ec_point_formats:支持的曲線點格式,默認都是 uncompressed。

2、服務端回復 server_hello,包含一個隨機數 random2 及 ECC 擴展。

3、服務端回復 certificate,攜帶了證書公鑰。

4、服務端生成 ECDH 臨時公鑰,同時回復 server_key_exchange,包含三部分重要內容:

a)ECC 相關的參數。

b)ECDH 臨時公鑰。

c)ECC 參數和公鑰生成的簽名值,用于客戶端校驗。

5、瀏覽器接收 server_key_exchange 之后,使用證書公鑰進行簽名解密和校驗,獲取服務器端的 ECDH 臨時公鑰,生成會話所需要的共享密鑰。

至此,瀏覽器端完成了密鑰協商。

6、瀏覽器生成 ECDH 臨時公鑰和 client_key_exchange 消息,跟 RSA 密鑰協商不同的是,這個消息不需要加密了。

7、服務器處理 client_key_exchang 消息,獲取客戶端 ECDH 臨時公鑰。

8、服務器生成會話所需要的共享密鑰。

9、Server 端密鑰協商過程結束。

圖示如下:

圖 7 ECDHE 密鑰協商過程

3.1.2 對稱內容加密

非對稱密鑰交換過程結束之后就得出了本次會話需要使用的對稱密鑰。對稱加密又分為兩種模式:流式加密和分組加密。流式加密現在常用的就是 RC4,不過 RC4 已經不再安全,微軟也建議網站盡量不要使用 RC4 流式加密。

一種新的替代 RC4 的流式加密算法叫 ChaCha20,它是 Google 推出的速度更快,更安全的加密算法。目前已經被 android 和 chrome 采用,也編譯進了 google 的開源 openssl 分支 —boring ssl,并且nginx 1.7.4 也支持編譯 boringssl。

分組加密以前常用的模式是 AES-CBC,但是 CBC 已經被證明容易遭受BEAST和LUCKY13 攻擊。目前建議使用的分組加密模式是 AES-GCM,不過它的缺點是計算量大,性能和電量消耗都比較高,不適用于移動電話和平板電腦。

3.2 身份認證

身份認證主要涉及到 PKI 和數字證書。通常來講 PKI(公鑰基礎設施)包含如下部分

End entity:終端實體,可以是一個終端硬件或者網站。

CA:證書簽發機構。

RA:證書注冊及審核機構。比如審查申請網站或者公司的真實性。

CRL issuer:負責證書撤銷列表的發布和維護。

Repository:負責數字證書及 CRL 內容存儲和分發。

申請一個受信任的數字證書通常有如下流程:

1、終端實體生成公私鑰和證書請求。

2、RA 檢查實體的合法性。如果個人或者小網站,這一步不是必須的。

3、CA 簽發證書,發送給申請者。

4、證書更新到 repository,終端后續從 repository 更新證書,查詢證書狀態等。

目前百度使用的證書是 X509v3 格式,由如下三個部分組成:

1、tbsCertificate(to be signed certificate 待簽名證書內容),這部分包含了 10 個要素,分別是版本號,序列號,簽名算法標識,發行者名稱,有效期,證書主體名,證書主體公鑰信息,發行商唯一標識,主體唯一標識,擴展等。

2、signatureAlgorithm,簽名算法標識,指定對 tbsCertificate 進行簽名的算法。

3、signaturValue(簽名值),使用 signatureAlgorithm 對 tbsCertificate 進行計算得到簽名值。

數字證書有兩個作用:

1、身份授權。確保瀏覽器訪問的網站是經過 CA 驗證的可信任的網站。

2、分發公鑰。每個數字證書都包含了注冊者生成的公鑰。在 SSL 握手時會通過 certificate 消息傳輸給客戶端。比如前文提到的 RSA 證書公鑰加密及 ECDHE 的簽名都是使用的這個公鑰。

申請者拿到 CA 的證書并部署在網站服務器端,那瀏覽器發起握手接收到證書后,如何確認這個證書就是 CA 簽發的呢?怎樣避免第三方偽造這個證書?

答案就是數字簽名(digital signature)。數字簽名是證書的防偽標簽,目前使用最廣泛的 SHA-RSA 數字簽名的制作和驗證過程如下:

1、數字簽名的簽發。首先是使用哈希函數對待簽名內容進行安全哈希,生成消息摘要,然后使用 CA 自己的私鑰對消息摘要進行加密。

2、數字簽名的校驗。使用 CA 的公鑰解密簽名,然后使用相同的簽名函數對待簽名證書內容進行簽名并和服務端數字簽名里的簽名內容進行比較,如果相同就認為校驗成功。


圖 8 數字簽名生成及校驗

這里有幾點需要說明:

1、數字簽名簽發和校驗使用的密鑰對是 CA 自己的公私密鑰,跟證書申請者提交的公鑰沒有關系。

2、數字簽名的簽發過程跟公鑰加密的過程剛好相反,即是用私鑰加密,公鑰解密。

3、現在大的 CA 都會有證書鏈,證書鏈的好處一是安全,保持根 CA 的私鑰離線使用。第二個好處是方便部署和撤銷,即如果證書出現問題,只需要撤銷相應級別的證書,根證書依然安全。

4、根 CA 證書都是自簽名,即用自己的公鑰和私鑰完成了簽名的制作和驗證。而證書鏈上的證書簽名都是使用上一級證書的密鑰對完成簽名和驗證的。

5、怎樣獲取根 CA 和多級 CA 的密鑰對?它們是否可信?當然可信,因為這些廠商跟瀏覽器和操作系統都有合作,它們的公鑰都默認裝到了瀏覽器或者操作系統環境里。比如firefox 就自己維護了一個可信任的 CA 列表,而chrome 和 IE 使用的是操作系統的 CA 列表。

4.3 數據完整性

這部分內容比較好理解,跟平時的 md5 簽名類似,只不過安全要求要高很多。openssl 現在使用的完整性校驗算法有兩種:MD5 或者 SHA。由于 MD5 在實際應用中存在沖突的可能性比較大,所以盡量別采用 MD5 來驗證內容一致性。SHA 也不能使用 SHA0 和 SHA1,中國山東大學的王小云教授在 2005 年就宣布破解了 SHA-1 完整版算法。

微軟和 google 都已經宣布 16 年及 17 年之后不再支持 sha1 簽名證書。

5 HTTPS 使用成本

HTTPS 目前唯一的問題就是它還沒有得到大規模應用,受到的關注和研究都比較少。至于使用成本和額外開銷,完全不用太過擔心。

一般來講,使用 HTTPS 前大家可能會非常關注如下問題:

1、證書費用以及更新維護。大家覺得申請證書很麻煩,證書也很貴,可是證書其實一點都不貴,便宜的一年幾十塊錢,最多也就幾百。而且現在也有了免費的證書機構,比如著名的 mozilla 發起的免費證書項目:let’s encrypt(https://letsencrypt.org/)就支持免費證書安裝和自動更新。這個項目將于今年中旬投入正式使用。

數字證書的費用其實也不高,對于中小網站可以使用便宜甚至免費的數字證書服務(可能存在安全隱患),像著名的 verisign 公司的證書一般也就幾千到幾萬塊一年不等。當然如果公司對證書的需求比較大,定制性要求高,可以建立自己的 CA 站點,比如 google,能夠隨意簽發 google 相關證書。

2、HTTPS 降低用戶訪問速度。HTTPS 對速度會有一定程度的降低,但是只要經過合理優化和部署,HTTPS 對速度的影響完全可以接受。在很多場景下,HTTPS 速度完全不遜于 HTTP,如果使用 SPDY,HTTPS 的速度甚至還要比 HTTP 快。

大家現在使用百度 HTTPS 安全搜索,有感覺到慢嗎?

3、HTTPS 消耗 CPU 資源,需要增加大量機器。前面介紹過非對稱密鑰交換,

4、消耗 CPU 計算資源的大戶,此外,對稱加解密,也需要 CPU 的計算。

5、同樣地,只要合理優化,HTTPS 的機器成本也不會明顯增加。對于中小網站,完全不需要增加機器也能滿足性能需求。


大型網站的 HTTPS 實踐(2):HTTPS 對性能的影響

1 前言

HTTPS 在保護用戶隱私,防止流量劫持方面發揮著非常關鍵的作用,但與此同時,HTTPS 也會降低用戶訪問速度,增加網站服務器的計算資源消耗。

本文主要介紹 HTTPS對用戶體驗的影響。

2 HTTPS 對訪問速度的影響

在介紹速度優化策略之前,先來看下 HTTPS 對速度有什么影響。影響主要來自兩方面:

  1. 協議交互所增加的網絡 RTT(round trip time)。

  2. 加解密相關的計算耗時。

下面分別介紹一下。

2.1 網絡耗時增加

由于 HTTP 和 HTTPS 都需要 DNS 解析,并且大部分情況下使用了 DNS 緩存,為了突出對比效果,忽略主域名的 DNS 解析時間。

用戶使用 HTTP 協議訪問http://www.baidu.com(或者 www.baidu.com) 時會有如下網絡上的交互耗時:



圖 1 HTTP 首個請求的網絡耗時

可見,用戶只需要完成 TCP 三次握手建立 TCP 連接就能夠直接發送 HTTP 請求獲取應用層數據,此外在整個訪問過程中也沒有需要消耗計算資源的地方。

接下來看 HTTPS 的訪問過程,相比 HTTP 要復雜很多,在部分場景下,使用 HTTPS 訪問有可能增加 7 個 RTT。如下圖:



圖 2 HTTPS 首次請求對訪問速度的影響

HTTPS 首次請求需要的網絡耗時解釋如下:

1,    三次握手建立 TCP 連接。耗時一個 RTT。

2,    使用 HTTP 發起 GET 請求,服務端返回 302 跳轉到 https://www.baidu.com。需要一個 RTT 以及 302 跳轉延時。

a)       大部分情況下用戶不會手動輸入 https://www.baidu.com 來訪問 HTTPS,服務端只能返回 302 強制瀏覽器跳轉到 https。

b)      瀏覽器處理 302 跳轉也需要耗時。

3,    三次握手重新建立 TCP 連接。耗時一個 RTT。

a)       302 跳轉到 HTTPS 服務器之后,由于端口和服務器不同,需要重新完成三次握手,建立 TCP 連接。

4,    TLS 完全握手階段一。耗時至少一個 RTT。

a)       這個階段主要是完成加密套件的協商和證書的身份認證。

b)      服務端和瀏覽器會協商出相同的密鑰交換算法、對稱加密算法、內容一致性校驗算法、證書簽名算法、橢圓曲線(非 ECC 算法不需要)等。

c)       瀏覽器獲取到證書后需要校驗證書的有效性,比如是否過期,是否撤銷。

5,    解析 CA 站點的 DNS。耗時一個 RTT。

a)       瀏覽器獲取到證書后,有可能需要發起 OCSP 或者 CRL 請求,查詢證書狀態。

b)      瀏覽器首先獲取證書里的 CA 域名。

c)       如果沒有命中緩存,瀏覽器需要解析 CA 域名的 DNS。

6,    三次握手建立 CA 站點的 TCP 連接。耗時一個 RTT。

a)       DNS 解析到 IP 后,需要完成三次握手建立 TCP 連接。

7,    發起 OCSP 請求,獲取響應。耗時一個 RTT。

8,    完全握手階段二,耗時一個 RTT 及計算時間。

a)       完全握手階段二主要是密鑰協商。

9,    完全握手結束后,瀏覽器和服務器之間進行應用層(也就是 HTTP)數據傳輸。

當然不是每個請求都需要增加 7 個 RTT 才能完成 HTTPS 首次請求交互。大概只有不到 0.01% 的請求才有可能需要經歷上述步驟,它們需要滿足如下條件:

1,    必須是首次請求。即建立 TCP 連接后發起的第一個請求,該連接上的后續請求都不需要再發生上述行為。

2,    必須要發生完全握手,而正常情況下 80% 的請求能實現簡化握手。

3,    瀏覽器需要開啟 OCSP 或者 CRL 功能。Chrome 默認關閉了 ocsp 功能,firefox 和 IE 都默認開啟。

4,    瀏覽器沒有命中 OCSP 緩存。Ocsp 一般的更新周期是 7 天,firefox 的查詢周期也是 7 天,也就說是 7 天中才會發生一次 ocsp 的查詢。

5,    瀏覽器沒有命中 CA 站點的 DNS 緩存。只有沒命中 DNS 緩存的情況下才會解析 CA 的 DNS。

2.2 計算耗時增加

上節還只是簡單描述了 HTTPS 關鍵路徑上必須消耗的純網絡耗時,沒有包括非常消耗 CPU 資源的計算耗時,事實上計算耗時也不?。?0ms 以上),從瀏覽器和服務器的角度分別介紹一下:

1,    瀏覽器計算耗時

a)       RSA 證書簽名校驗,瀏覽器需要解密簽名,計算證書哈希值。如果有多個證書鏈,瀏覽器需要校驗多個證書。

b)      RSA 密鑰交換時,需要使用證書公鑰加密 premaster。耗時比較小,但如果手機性能比較差,可能也需要 1ms 的時間。

c)       ECC 密鑰交換時,需要計算橢圓曲線的公私鑰。

d)      ECC 密鑰交換時,需要使用證書公鑰解密獲取服務端發過來的 ECC 公鑰。

e)       ECC 密鑰交換時,需要根據服務端公鑰計算 master key。

f)       應用層數據對稱加解密。

g)      應用層數據一致性校驗。

2,    服務端計算耗時

a)       RSA 密鑰交換時需要使用證書私鑰解密 premaster。這個過程非常消耗性能。

b)      ECC 密鑰交換時,需要計算橢圓曲線的公私鑰。

c)       ECC 密鑰交換時,需要使用證書私鑰加密 ECC 的公鑰。

d)      ECC 密鑰交換時,需要根據瀏覽器公鑰計算共享的 master key。

e)       應用層數據對稱加解密。

f)       應用層數據一致性校驗。

由于客戶端的 CPU 和操作系統種類比較多,所以計算耗時不能一概而論。手機端的 HTTPS 計算會比較消耗性能,單純計算增加的延遲至少在 50ms 以上。PC 端也會增加至少 10ms 以上的計算延遲。

服務器的性能一般比較強,但由于 RSA 證書私鑰長度遠大于客戶端,所以服務端的計算延遲也會在 5ms 以上。

3 結束語

本系列的后續文章將進一步解釋針對性的優化措施。


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

timg (8).jpg

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 推薦的密鑰長度對照表。


表格 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 硬件加速集群?;舅悸肥牵?/p>

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 的接入和對它的優化,在產品和運維層面上花費的功夫會更多。本系列的下一篇文章將進一步進行介紹。


大型網站的 HTTPS 實踐(4):協議層以外的實踐

1 前言

網上介紹 HTTPS  的文章并不多,更鮮有分享在大型互聯網站點部署 HTTPS  的實踐經驗,我們在考慮部署HTTPS 時也有重重的疑惑。

本文為大家介紹百度 HTTPS 的實踐和一些權衡, 希望以此拋磚引玉。

timg (7).jpg

2 協議層以外的實踐工作

2.1 全站覆蓋 https 的理由

很多剛接觸 https 的會思考,我是不是只要站點的主域名換了HTTPS 就可以?答案是不行。

HTTPS的目的就是保證傳輸過程的安全,如果只有主域名上了 HTTPS ,但是主域名加載的資源,比如 js,css,圖片沒有上 HTTPS ,會怎么樣?

從效果上來說,沒有達到保證網站傳輸過程安全的目的,因為你的 js,css,圖片仍然有被劫持的可能性,如果這些內容被篡改 / 嗅探了,那么 HTTPS  的意義就失去了。

瀏覽器在設計上早就考慮的這樣的情況,會有相應的提示。具體的實現依賴瀏覽器,例如地址欄鎖形標記從綠色變為黃色, 阻止這次請求,或者直接彈出非常影響用戶體驗的提示 (主要是 IE),用戶會感覺厭煩,疑惑和擔憂安全性。


很多用戶看見這個鏈接會習慣性的點”是”,這樣非 HTTPS  的資源就被禁止加載了。非 ie 的瀏覽器很多也會阻止加載一些危害程度較高的非 HTTPS  資源(例如 js)。我們發現移動端瀏覽器的限制目前會略松一些。

所以這里要是沒做好,很多情況連網站的基本功能都沒法正常使用。

2.2 站點的區別

很多人剛接觸 HTTPS  的時候,覺得不就是部署證書,讓 webserver 支持HTTPS 就行了嗎。

實際上對于不同的站點來說,HTTPS 的部署方式和難度有很大的區別。對于一個大型站點來說,讓 webserver 支持 HTTPS ,以及對 webserver 在 HTTPS 協議特性上做一些優化,在遷移的工作比重上,可能只占到 20%-40%。

我們考慮下以下幾種情況下,部署HTTPS  的方案。

2.2.1 簡單的個人站點

簡單的定義:資源只從本站的主域或者主域的子域名加載。

比如 axyz 的個人 blog,域名是 axyzblog.com。加載主域名下的 js 和圖片。


這樣的站部署 https,在已有證書且 webserver 支持的情況下,只需要把主域名替換為 HTTPS  接入,然后把資源連接修改為 https:// 或者 //。

2.2.2 復雜的個人站點

復雜的定義:資源需要從外部域名加載。


這樣就比較麻煩了,主域資源容易適配 HTTPS ,在 cdn 上加載的資源還需要 cdn 服務商支持 HTTPS 。目前各大 cdn 的服務商正在逐漸提供HTTPS  的支持,需要遷移的朋友可以看看自己使用的 cdn 是否提供了這項能力。一些 cdn 會對 HTTPS  流量額外收費。


Cdn 使用HTTPS 常見的方案有:

1 網站主提供私鑰給 cdn,回源使用HTTP。

2 cdn 使用公共域名,公共的證書,這樣資源的域名就不能自定義了?;卦词褂?nbsp;HTTP。

3 僅提供動態加速,cdn 進行 tcp 代理,不緩存內容。

4 CloudFlare 提供了Keyless SSL的服務,能夠支持不愿意提供私鑰, 不想使用公共的域名和證書卻又需要使用 cdn 的站點了。

2.2.3 簡單的大型站點

簡單的定義: 資源只從本站的主域, 主域的子域,或者自建 / 可控的 cdn 域名加載,幾乎沒有第三方資源。如果網站本身的特性就如此,或愿意改造為這樣的類型,部署 https 就相對容易。Google Twitter 都是非常好的范例。優點:已經改成這樣的站點,替換 https 就比較容易。缺點:如果需要改造,那么要很大的決心,畢竟幾乎不能使用多樣化的第三方資源了。

2.2.4 復雜,訪問速度重要性稍低的大型站點

復雜的定義:從本站的非主域,或者第三方站點的域名有大量的第三方資源需要加載,多出現在一些平臺類,或者有復雜內容展現的的網站。

訪問速度要求:用戶停留時間長或者強需求,用戶對訪問速度的耐受程度較高。比如門戶,視頻,在線交易類(比如火車票 機票 商城)網站。

這樣的站點,可以努力推動所有相關域名升級為支持 HTTPS 。我們用下圖舉例說明下這樣修改會導致一個網站的鏈接發生怎樣的改變。


負責流量接入的團隊將可控的接入環境改造為 HTTP 和 HTTPS  都支持,這樣前端工程的工作相對就少一些。大部分時候將鏈接從 http:// 替換為 // 即可. 在主域名是 HTTPS  的情況下,其它資源就能自動從 HTTPS  協議下加載。一些第三方資源怎么辦?一般來說只有兩種選擇,一遷移到自己的 cdn 或者 idc 吧,二強制要求第三方自己能支持 HTTPS 。

以全站 HTTPS  接入的 facebook 舉例。第三方廠商想在 facebook 上線一個游戲。facebook:請提供HTTPS 接入吧。第三方想:能賺錢啊,還是提供下 HTTPS 接入吧。所以,足夠強勢,有吸引力,合作方也有提供 HTTPS  的能力的話,這是完全可行的。如果你的平臺接入的都是一些個人開發者,而且還賺不到多少錢的情況下,這樣就行不通了。

優點:前端改動相對簡單,不容易出現 HTTPS  下還有 http 的資源問題。

缺點:通常這樣的實現下,用戶的訪問速度會變慢,比如從 2.5 秒變為 3 秒,如上述的理由,用戶還是能接受的。對第三方要求高。

2.2.5 復雜,訪問速度有嚴格要求的大型站點

復雜的定義:同上。

訪問速度要求:停留時間不長,用戶對訪問速度的心理預期較高。

但是如果用戶把網站當作工具使用,需要你很快給出響應的時候,這樣的實現就不好了。后續幾個部分我們介紹下這些優化的抉擇。

2.3 域名的選擇

域名對訪問速度的影響具有兩面性:域名多,域名解析和建立連接的時間就多;域名少,下載并發度又不夠。

HTTPS  下重建連接的時間成本比HTTP 更高,對于上面提到的簡單的大型站點, 可以用少量域名就能滿足需求,對于百度這樣富展現樣式較多的搜索引擎來說,頁面可能展示的資源種類太多。而不同類型的資源又是由不同的域名 (不同的產品 或者第三方產品) 提供的服務,換一個詞搜索就可能需要重新建立一些資源的 ssl 鏈接,會讓用戶感受到卡頓。


如果將域名限制在有限的范圍,維持和這些域名的連接,合并一些數據,加上有 spdy,http2.0 來保證并發,是可以滿足我們的需求的。

2.4 連接復用

連接復用率可以分為 tcp 和 ssl 等不同的層面,需要分開進行分析和統計。

2.4.1 連接復用的意義

HTTP 協議 (RFC2616) 規定一個域名最多不能建立超過 2 個的 TCP 連接。但是隨著互聯網的發展,一張網頁的元素越來越多,傳輸內容越來越大,一個域名 2 個連接的限制已經遠遠不能滿足現在網頁加載速度的需求。

目前已經沒有瀏覽器遵守這個規定,各瀏覽器針對單域名建立的 TCP 連接數如下:


表格 1 瀏覽器單域名建立的最大并發連接數

從上表看出,單個域名的連接數基本上是 6 個。所以只能通過增加域名的方式來增加并發連接數。在 HTTP 場景下,這樣的方式沒有什么問題。但是在 HTTPS 連接下,由于 TLS 連接建立的成本比較高,增加并發連接數本身就會帶來較大的延遲,所以對域名數需要一個謹慎的控制。

特別是 HTTP2 即將大規模應用,而 HTTP2 的最大特性就是多路復用,使用多個域名和多個連接無法有效發揮多路復用和壓縮的特性。

那 HTTPS 協議下,一張網頁到底該有多少域名呢?這個其實沒有定論,取決于網頁需要加載元素個數。

2.4.2 預建連接

既然從協議角度無法減少握手對速度的影響,那能不能提前建立連接,減少用戶可以感知的握手延遲呢?當然是可以的。思路就是預判當前用戶的下一個訪問 URL,提前建立連接,當用戶發起真實請求時,TCP 及 TLS 握手都已經完成,只需要在連接上發送應用層數據即可。

最簡單有效的方式就是在主域下對連接進行預建,可以通過請求一些靜態資源的方式。但是這樣還是不容易做到極致,因為使用哪個連接,并發多少還是瀏覽器控制的。例如你對 a 域名請求一個圖片,瀏覽器建立了兩個連接,再請求一張圖片的時候,瀏覽器很大概率能夠復用連接,但是當 a 域名需要加載 10 個圖片的時候,瀏覽器很可能就會新建連接了。

2.4.3 Spdy 的影響

Spdy 對于連接復用率的提升非常有效,因為它能支持連接上的并發請求,所以瀏覽器會盡量在這個鏈接上保持復用。

2.4.4 其它

也可以嘗試一些其他發方法,讓瀏覽器在訪問你的網站之前就建立過 HTTP2 連接,這樣 session 能夠復用。HSTS 也能有效的減少跳轉時間,可惜對于復雜的網站來說,開啟需要考慮清楚很多問題。

2.5 優化的效果

從百度的優化經驗來看看,如果不開啟 HSTS,用戶在瀏覽器直接訪問主域名,再通過 302 跳轉到 HTTPS。增加的時間平均會有 400ms+,其中 302 跳轉和 ssl 握手的因素各占一半。但是對于后續的請求,我們做到了對絕大部分用戶幾乎無感知。

這 400ms+ 還有很多可以優化的空間,我們會持續優化用戶的體驗。

3 HTTPS 遷移遇到的一些常見問題

3.1 傳遞 Referrer

我們可以把自己的網站替換為 HTTPS,但是一般的站點都有外鏈,要讓外鏈都 HTTPS 目前還不太現實。很多網站需要從 referrer 中判斷流量來源,因此對于搜索引擎這樣的網站來說,referer 的傳遞還是比較重要的。如果不做任何設置,你會發現在HTTPS站點中點擊外鏈并沒有將 referrer 帶入到HTTP請求的頭部中(http://tools.ietf.org/html/rfc7231#section-5.5.2)?,F代的瀏覽器可以用 meta 標簽來傳遞 refer。(http://w3c.github.io/webappsec/specs/referrer-policy)

<meta name=”referrer” content=”always”> 傳遞完整的 url

<meta name=”referrer” content=”origin”> 只傳遞站點,不包含路徑和參數等。

對于不支持 meta 傳遞 referrer 的瀏覽器,例如 IE8, 我們怎么辦呢?

可以采用再次跳轉的方法,既然 HTTPS 下不能給 HTTP 傳遞 referer,我們可以先從 HTTPS 訪問一個可控的 HTTP 站點,把需要傳遞的內容放到這個 HTTP 站點的 url 中,然后再跳轉到目標地址。


3.2 form 提交

有時需要將 form 提交到第三方站點,而第三方站點又是 HTTP 的地址,瀏覽器會有不安全的警告??梢院?referrer 的跳轉傳遞采取相似的邏輯。

但是這樣對 referer 和 form 等內容的方案,并不是完美的解決方法,因為這樣還是增加了不安全的因素(劫持,隱私泄露等 )。理想情況需要用戶升級符合最新規范的瀏覽器,以及推進更多的站點遷移至 HTTPS。

3.3 視頻播放

簡單來說,如果你使用 http 的協議來播放視頻,那么瀏覽器仍然會有不安全的提示。所以你有兩種選擇,1 讓視頻源提供 HTTPS。2 使用非 HTTP 的協議,如 rtmp 協議。

3.4 用戶異常

在 HTTP 遷移的過程中,也會有不少熱心的用戶向我們反饋遇到的各種問題。

常見的有以下的一些情況:

1 用戶的系統時間設置錯誤,導致提示證書過期。

2 用戶使用 fiddler 等代理進行調試,但是沒有添加這些軟件的根證書,導致提示證書非法。

3 用戶使用的 Dns 為公共 dns 或者跨網設置 dns,一些請求被運營商作為跨網流量攔截。

4 連通性有問題,我們發現一個小運營商的 https 失敗率奇高,又沒法聯系到他們,只能不對他們進行 HTTPS 的轉換。

5 慢。有時由于網絡環境的因素,用戶打開其他網站也慢,ping 哪個網站都要 500-2000ms。這時 https 自然也會很慢。

4 結束語

對于復雜的大型網站來說,HTTPS 的部署有很多工作要完成。

面對困難和挑戰,有充足的動力支持著我們前進:https 上線后,劫持等原因導致的用戶功能異常,隱私泄露的反饋大幅減少。

熱心的用戶經常會向我們反饋遇到的各種問題。在以前,有時即使我們確定了是劫持的問題,能夠解決問題的方法也非常有限。每當這種時候,自己總會產生一些無力感。

HTTPS 的全站部署,給我們提供了能解決大部分問題的選項。能讓一個做技術的人看到自己的努力解決了用戶的問題,這就是最棒的收獲。

HTTPS 沒有想像中難用和可怕,只是沒有經過優化。與大家共勉。


大型網站的 HTTPS 實踐相關百科

    沒有找到您想要的百科