全站(zhàn)HTTPS沒你(nǐ)想象的那(nà)麽簡單,電(diàn)商網站(zhàn)兼顧安全與性能的踩坑小(xiǎo)結!
- 作(zuò)者:admin
- 發表時(shí)間(jiān):2017-09-12 10:35:01
- 來(lái)源:未知
注:衆所周知,數(shù)據 HTTP 明(míng)文傳輸過程中,會(huì)遇到如劫持、篡改、監聽(tīng)、竊取等一系列問題,解決這一問題的方法就是做(zuò) HTTPS 改造。
HTTPS 的作(zuò)用是在會(huì)話(huà)層、表示層引入 TLS/SSL 握手協議,通(tōng)過數(shù)據加密、解密方式,來(lái)應對數(shù)據明(míng)文傳輸過程中遇到的問題,保障數(shù)據的完整性、一緻性,為(wèi)用戶帶來(lái)更安全的網絡體(tǐ)驗、更好的隐私保護。
然而,HTTPS 增加了 TLS/SSL 握手環節,再加上(shàng)應用數(shù)據傳輸需要經過對稱加密,對性能提出了更大(dà)的挑戰。
作(zuò)為(wèi)一個(gè)好的架構,一定要均衡安全和(hé)性能兩方面,如果讓天秤向任何一方傾斜過多(duō),都會(huì)影(yǐng)響最終的用戶體(tǐ)驗。
因此,為(wèi)了兼顧安全與性能,蘇甯的全站(zhàn) HTTPS 改造從 2015 年底開(kāi)始進行(xíng),曆時(shí)一年多(duō)時(shí)間(jiān),主要做(zuò)了系統 HTTPS 改造、HTTPS 性能優化和(hé) HTTPS 灰度上(shàng)線這三方面工作(zuò),讓用戶在 HTTPS 下訪問能夠獲得(de)極緻體(tǐ)驗成為(wèi)了可(kě)能。
全站(zhàn) HTTPS 方案概述
蘇甯易購從 2015 年開(kāi)始規劃做(zuò) HTTPS 相關的事情,當時(shí)可(kě)借鑒的資料非常少(shǎo),電(diàn)商類網站(zhàn)相關的 HTTPS 改造的詳盡案例更是難求。
如下圖,是蘇甯易購全站(zhàn)的 HTTPS 方案:
如圖中所示,整個(gè)方案分三步構建,分别是系統改造、性能優化和(hé)灰度上(shàng)線:
系統改造。原有(yǒu)系統想要支持 HTTPS,必須進行(xíng)改造,首先要建立 HTTPS 接入層,也就是開(kāi)通(tōng) 443 端口,讓所有(yǒu)的應用系統支持 HTTPS 訪問。
在此基礎上(shàng)做(zuò)頁面資源替換,解決當一個(gè) HTTPS 頁面出現 HTTP 請(qǐng)求時(shí)就會(huì)出現錯誤的問題。做(zuò)完這兩件事,CDN 上(shàng)證書(shū)的處理(lǐ)、HTTPS 測試方案等問題也就迎刃而解。
性能優化。做(zuò)系統改造,增加兩次 TLS 握手,必然會(huì)對性能造成一定的開(kāi)銷和(hé)損失,如何去彌補性能的損失,達到性能和(hé)安全兼顧呢?性能優化部分包含若幹優化點,下文會(huì)詳細展開(kāi)。
灰度上(shàng)線。這部分是時(shí)間(jiān)花(huā)費最多(duō)的,HTTPS 一步步上(shàng)線的過程中,踩坑最多(duō),其中部分是前面沒有(yǒu)發現的問題。
這證明(míng)不能一次性将整個(gè)全站(zhàn)、全地區(qū)、全用戶一次性堆成 HTTPS,可(kě)以根據流量所處的運營商和(hé)城市及用戶級别去做(zuò)灰度上(shàng)線。
HTTPS 方案之系統改造篇
01、HTTPS 接入層定義
系統改造的頭等大(dà)事是開(kāi)通(tōng) 443 端口,成熟的網絡系統會(huì)包含 CDN、硬件負載均衡、應用防火(huǒ)牆、Web 服務器(qì)、應用服務器(qì),最後到數(shù)據層。難道(dào)整個(gè)鏈路都要做(zuò) HTTPS?在每層都增加 SSL 握手消耗嗎?答(dá)案是否定的。
所以,應該盡早完成 SSL 握手,做(zuò) SSL 過程中首要考慮的是 HTTPS 接入層的定位。
如下圖,是蘇甯易購架構中 HTTPS 接入層的位置:
如圖中所示,我們把 HTTPS 接入層放在 CDN 和(hé)應用系統之間(jiān),采用四層+七層負載均衡的架構。
四層負載并不處理(lǐ) HTTPS 卸載,它的主要職責是做(zuò) TCP 的分發。在七層負載完成整個(gè) SSL 握手,而後面應用系統走 80 端口,這樣就相當于完成了 HTTPS 整個(gè)卸載的過程。
這樣做(zuò)的好處,一方面,系統應用層面不需要為(wèi) HTTPS 做(zuò)任何調整;另一方面,将來(lái)所有(yǒu) HTTPS 的調度、優化和(hé)配置都可(kě)以在接入層完成。
02、頁面資源替換
第一步,理(lǐ)解 Mixed Content
對于一個(gè)頁面而言,請(qǐng)求頁面的請(qǐng)求是用 HTTPS 加載,一旦內(nèi)部頁面元素有(yǒu) HTTP 的性質,這時(shí) RFC 标準裏就會(huì)出現一個(gè)錯誤,叫 Mixed Content(混淆錯誤)。
所以,如果要加載一個(gè)安全的 HTTPS 頁面,就不應該在其中混淆 HTTP 請(qǐng)求。
第二步,// 替換 http://
用 // 替換 http://,這樣就可(kě)以讓頁面所有(yǒu)的元素做(zuò)一個(gè)适配,去遵循原來(lái)的請(qǐng)求。
第三步,x-request-url 的定義和(hé)使用
當然,我們在//替換過程中也遇到了一些(xiē)坑。舉個(gè)例子,下圖是蘇甯易購單點登錄系統交互的過程:
如圖中所示,當用戶 authID 失效,發起請(qǐng)求 https://xxx.suning.com/authStatus 鑒權,接入層會(huì)對所有(yǒu)請(qǐng)求做(zuò)卸載,地址就會(huì)變成 HTTP。
進入業務系統做(zuò)鑒權的話(huà),Reponse 302 就會(huì)跳(tiào)轉到單點登錄系統。這時(shí)會(huì)将第二步的頁面記錄為(wèi)原始頁面,返回到用戶端,用戶去請(qǐng)求單點登錄系統,單點登錄系統完成鑒權以後,再回跳(tiào)時(shí),是 HTTP 地址,最終導緻用戶端 MixContent。
因此,我們引入 x-request-url 解決問題,如下圖:
所有(yǒu)原始請(qǐng)求協議都記錄在 x-request-url 中,如果業務系統鑒權,一定要遵循 x-request-url 記錄的協議,就可(kě)應對回跳(tiào)導緻的用戶端 Mix Content 問題。
03、App 原生(shēng)無法識别//的問題
出現浏覽器(qì)可(kě)以識别 //,但(dàn) App 原生(shēng)無法識别 // 的原因很(hěn)簡單,因為(wèi)浏覽器(qì)本身做(zuò)了适配。
當時(shí),蘇甯服務端有(yǒu)一個(gè)系統,專門(mén)提供一個(gè)接口,向各個(gè)端提供圖片。做(zuò)完 HTTPS 改造之後,PC 端和(hé)客戶端都沒有(yǒu)問題。但(dàn)是第二天,很(hěn)多(duō)用戶突然就不能加載圖片,原因是請(qǐng)求在 APP 原生(shēng)情況下沒法識别 //。
這裏的解決方法,隻能是客戶端開(kāi)發人(rén)員做(zuò)适配,下圖是 App 無法識别//的一個(gè)例子:
4、如何處理(lǐ)商用 CDN 上(shàng)的證書(shū)和(hé)私鑰?
CPN 證書(shū)的處理(lǐ)是大(dà)多(duō)數(shù)小(xiǎo)型互聯網企業都會(huì)遇到的問題。因為(wèi)這些(xiē)小(xiǎo)企業不像阿裏、京東可(kě)自建 CDN,蘇甯也是一樣。
蘇甯的 CDN 由自建和(hé)商用兩種組成,一旦使用商用 CDN,就會(huì)面臨 HTTPS 如何過去的問題。
企業隻要将私鑰給到第三方或廠商之後,在所有(yǒu)廠商的 CDN 服務器(qì)都沒辦法控制(zhì)。當有(yǒu)黑(hēi)客攻擊完廠商服務器(qì)後,加密已沒任何意義,因為(wèi)私鑰已經洩露。
如下圖,業界比較公認的應對方式分别是:雙證書(shū)的策略、四層加速和(hé) Keyless 解決方案。
雙證書(shū)的策略。它的思想很(hěn)簡單,相當于用戶到 CDN 端,提供的是 CDN 的證書(shū),做(zuò)加解密。從 CDN 到應用服務器(qì)端用的是應用自有(yǒu)的證書(shū)來(lái)做(zuò)加解密。
這樣的方式,可(kě)以保證應用端的密鑰不用提供給 CDN 廠商,但(dàn)根本的問題還(hái)是沒有(yǒu)解決,那(nà)就是 CDN 廠商的證書(shū)仍然有(yǒu)洩露的可(kě)能。如果洩露了,用戶端還(hái)是會(huì)受到影(yǐng)響。
四層加速。很(hěn)多(duō) CDN 廠商都有(yǒu)能力提供 TCP 加速,做(zuò)動态、還(hái)原和(hé)擇優等。CDN 廠商隻做(zuò)四層模式和(hé) TCP 代理(lǐ),不考慮請(qǐng)求緩存。
這樣就沒必要将證書(shū)暴露給 CDN 廠商,這種方式适用于動态回源請(qǐng)求,比如加入購物車(chē)、提交訂單、登錄等。
Keyless 解決方案。适用于金融,提供一台實時(shí)計(jì)算(suàn)的 Key Server 。
當 CDN 要用到私鑰時(shí),通(tōng)過加密通(tōng)道(dào)将必要的參數(shù)傳給 Key Server,由 Key Server 算(suàn)出結果并返回即可(kě)。
05、HTTPS 測試策略
當引入一個(gè)新的協議,如何進行(xíng)測試呢?主要步驟,如下圖:
源碼掃描。當開(kāi)發人(rén)員完成資源替換後,利用 Jenkins 遍曆代碼庫,shell 腳本掃描出 HTTP 鏈接。
對頁面爬蟲掃描。我們會(huì)寫一些(xiē)爬蟲腳本,對測試環境的鏈接進行(xíng)掃描。
測試環境驗證。自動化測試固然好,但(dàn)是主要核心流程還(hái)是需要手動覆蓋一遍,防止 HTTPS 對頁面加載出現未知影(yǐng)響。
如有(yǒu)些(xiē)頁面是用 HTTPS 去訪問,可(kě)能這個(gè)系統還(hái)不支持 HTTPS,必須要手動驗證。
線上(shàng)預發和(hé)引流測試。HTTPS 的改造版本發到線上(shàng)對用戶來(lái)講是沒有(yǒu)影(yǐng)響的,因為(wèi)用戶使用的還(hái)是 HTTP 流量。
可(kě)以選擇線上(shàng)預發的方式,預發驗證完畢後,通(tōng)過 301 的方式,将用戶的流量從 HTTP 切到 HTTPS,這個(gè)後面講灰度時(shí)還(hái)會(huì)深入講解。
另外,我們還(hái)引入了引流測試系統:
它的思路很(hěn)簡單,根據域名、用戶請(qǐng)求做(zuò)捕獲,将所有(yǒu)捕獲流量放到 Copy Server 中去擴大(dà),放大(dà)若幹倍,然後通(tōng)過 Sender 再發送回到系統中。
這樣的方式,可(kě)以通(tōng)過用戶的真實流量,來(lái)驗證 HTTPS 的功能性和(hé)性能影(yǐng)響有(yǒu)多(duō)大(dà)。
HTTPS 方案之性能優化篇
談如何優化 HTTPS 的性能之前,我們先來(lái)看看整個(gè) TLS 握手流程,如下圖:
如圖中所示,一個(gè)握手過程最壞的情況下,要分為(wèi)八個(gè)步驟:
發送 Syn 包到 Web 客戶端,收到并确認後,同時(shí)發送 SynAck 到服務器(qì),這時(shí)還(hái)是一個(gè) HTTP 的請(qǐng)求。
HTTP 轉換 HTTPS,需要做(zuò)一次 302 或者 301 跳(tiào)轉。
用戶再次發送 HTTPS 請(qǐng)求,做(zuò)一次 TCP 握手。
做(zuò) TLS 完全握手第一階段,Clienthello 到 Server hello。
當證書(shū)首次到客戶端,客戶端需要走驗證流程,做(zuò) CA 域名解析。
第二次,TLS 握手。
在線證書(shū)合法性校(xiào)驗的過程。
TLS 完全握手第二階段,底部灰色部分才是真正的數(shù)據通(tōng)訊。
蘇甯易購的全站(zhàn) HTTPS 方案在性能優化方面做(zuò)了很(hěn)多(duō)事情,如 HSTS、Session resume、Ocsp stapling 的合理(lǐ)使用,如客戶端 HTTPS 性能、HttpDNS 解決 DNS 攻擊劫持等優化。
01、HSTS 的合理(lǐ)使用
Web 安全協議 HSTS 的作(zuò)用是強制(zhì)客戶端(如浏覽器(qì))使用 HTTPS 與服務器(qì)創建連接。
優點是減少(shǎo) HTTP 做(zuò) 302 跳(tiào)轉的開(kāi)銷。302 跳(tiào)轉不僅暴露了用戶的訪問站(zhàn)點,也很(hěn)容易被中間(jiān)者劫持(降級劫持、中間(jiān)人(rén)攻擊),最重要是降低(dī)了訪問速度(影(yǐng)響性能)。
缺點是 HSTS 在 max-age 過期時(shí)間(jiān)內(nèi),在客戶端是強制(zhì) HTTPS 的,服務端無法控制(zhì)。
因此,當需要降級時(shí),HTTPS 無法及時(shí)切換到 HTTP。當然你(nǐ)也可(kě)以通(tōng)過手動動态去配置 max-age 的值,這樣可(kě)以通(tōng)過将 max-age 設置為(wèi) 0 來(lái)達到降級效果。
還(hái)有(yǒu) HSTS 是嚴格的 HTTPS,一旦網絡證書(shū)錯誤時(shí),網頁将直接無法訪問(用戶無法選擇忽視(shì))。
02、Session resume 的合理(lǐ)使用
當用戶端和(hé)客戶端、客戶端和(hé)服務端完成第一次 TLS 握手之後,第二次數(shù)據傳輸還(hái)需要 TLS 握手嗎?
這裏可(kě)以采用 Session 複用的方式。Session resume(會(huì)話(huà)複用),是 RFC 标準中早就定好的一個(gè)機制(zhì),HTTPS 最初發布時(shí)就已經涉及其中。
Session 複用有(yǒu) Session ID 和(hé) Session tickets 兩種方式,下圖是實現流程:
Session ID。使用 clienthello 中的 session ID 查詢服務端的 session cache,如果服務端有(yǒu)對應的緩存,則直接使用已有(yǒu)的 session 信息提前完成握手,稱為(wèi)簡化握手。
Session ID 是 TLS 協議的标準字段,市面上(shàng)的浏覽器(qì)全部都支持 Session ID。需要注意的是,單機多(duō)進程間(jiān)共享 ssl session 對集群環境是沒有(yǒu)意義的。
因此,在這裏需要實現多(duō)機共享 Session ID。可(kě)以放在 redis 中,nginx 提供了專門(mén)處理(lǐ) Session ID 的模塊 ssl_session_fetch_by_lua_block。
Session tickets。Session tickets 是會(huì)話(huà) ID 的一種補充,server 将session 信息加密成 ticket 發送給浏覽器(qì),浏覽器(qì)在後續握手請(qǐng)求時(shí)會(huì)發送 ticket,server 端如果能成功解密和(hé)處理(lǐ) ticket,就能完成簡化握手。
顯然,session ticket 的優點是不需要服務端消耗大(dà)量資源來(lái)存儲 session 內(nèi)容。但(dàn)是 session ticket 隻是 TLS 協議的一個(gè)擴展特性,目前的支持率不是很(hěn)廣泛,隻有(yǒu) 60% 左右。
還(hái)需要維護一個(gè)全局的 KEY 來(lái)加解密,需要考慮 KEY 的安全性和(hé)部署效率。
03、Ocsp stapling 的合理(lǐ)使用
Ocsp 全稱在線證書(shū)狀态檢查協議 (rfc6960),用來(lái)向 CA 站(zhàn)點查詢證書(shū)狀态,比如證書(shū)是否被撤銷,是否已經過期等。
通(tōng)常情況下,浏覽器(qì)使用 OCSP 協議發起查詢請(qǐng)求,CA 返回證書(shū)狀态內(nèi)容,然後浏覽器(qì)接受證書(shū)是否可(kě)信的狀态。
如下圖,是 Ocsp 實現流程:
這個(gè)過程非常消耗時(shí)間(jiān),因為(wèi) CA 站(zhàn)點有(yǒu)可(kě)能在國外,導緻網絡不穩定,RTT 也比較大(dà)。那(nà)有(yǒu)沒有(yǒu)辦法不直接向 CA 站(zhàn)點請(qǐng)求 OCSP 內(nèi)容呢?
ocsp stapling 就能實現這個(gè)功能。ocspstapling 的原理(lǐ)簡單來(lái)說是服務端代替客戶端完成 CA 校(xiào)驗證書(shū)的過程,節省用戶端的時(shí)間(jiān)開(kāi)銷。
就是當浏覽器(qì)發起 clienthello 時(shí)會(huì)攜帶一個(gè) certificate status request 的擴展,服務端看到這個(gè)擴展後将 OCSP 內(nèi)容直接返回給浏覽器(qì),完成證書(shū)狀态檢查。
由于浏覽器(qì)不需要直接向 CA 站(zhàn)點查詢證書(shū)狀态,這個(gè)功能對訪問速度的提升非常明(míng)顯。
HTTPS 方案之灰度上(shàng)線篇
灰度上(shàng)線可(kě)遵循灰度、降級和(hé)開(kāi)閉三大(dà)原則。灰度原則是指整個(gè)上(shàng)線過程要按區(qū)域、版本、用戶等級來(lái)進行(xíng)灰度,通(tōng)過灰度收集上(shàng)來(lái)的用戶數(shù)據來(lái)決定整個(gè)計(jì)劃的進行(xíng)。
降級原則保證每一步的操作(zuò)都是可(kě)逆可(kě)回滾的,即對擴展開(kāi)放,對修改關閉,這是可(kě)複用設計(jì)的基石。
01、HTTPS 開(kāi)關控制(zhì)
HTTPS 開(kāi)關控制(zhì)方面,蘇甯主要建設內(nèi)容管理(lǐ)、CDN、客戶端三大(dà)開(kāi)關:
內(nèi)容管理(lǐ)開(kāi)關。內(nèi)容管理(lǐ)開(kāi)關的作(zuò)用是保證所有(yǒu)運營維護的鏈接都可(kě)以被替換。
CDN 開(kāi)關。每個(gè)頁面,從 HTTP 到 HTTPS 都需要做(zuò) 301 跳(tiào)轉,這些(xiē)跳(tiào)轉都配置在 CDN 中。
客戶端開(kāi)關。就是移動加速 SDK 的開(kāi)關。
02、上(shàng)線過程中遇到的新問題
做(zuò)完開(kāi)關控制(zhì),在正式上(shàng)線的過程中,又遇到了一些(xiē)新問題如:Referrer、DNS 劫持、HTTPS 性能監控等。
Referrer
目前大(dà)部分浏覽器(qì),在發生(shēng)協議降級時(shí)默認不發送 Referrer 信息,最典型的場(chǎng)景就是從 HTTPS 頁面點鏈接跳(tiào)到 HTTP 網站(zhàn)時(shí),浏覽器(qì)并不會(huì)在請(qǐng)求頭中帶上(shàng) Referer 字段。當 Referrer 帶不過去,對大(dà)數(shù)據的影(yǐng)響非常大(dà),因為(wèi)沒辦法追溯流量來(lái)源。
針對現代的浏覽器(qì),這個(gè)問題可(kě)以通(tōng)過給頁面加上(shàng)下面這個(gè) meta 标簽來(lái)解決:
DNS 劫持
DNS 劫持是指非法破壞域名的解析過程導緻請(qǐng)求被解析到一個(gè)錯誤節點以達到某些(xiē)惡意目的。當我們使用 HTTP時(shí),DNS 異常可(kě)能還(hái)不會(huì)影(yǐng)響請(qǐng)求的功能性,但(dàn) HTTPS 因為(wèi)非法節點沒有(yǒu)證書(shū)和(hé)私鑰,肯定是無法響應了。
蘇甯的做(zuò)法的是通(tōng)過一些(xiē)波測監控 DNS 的正常,如下圖,我們監測到蘇甯中華特色館在某個(gè)地區(qū)有(yǒu)大(dà)量 DNS 解析異常。
出現 DNS 劫持,對用戶影(yǐng)響很(hěn)大(dà),一旦出現一次頁面打不開(kāi),用戶就會(huì)認為(wèi)這個(gè)頁面有(yǒu)問題,不會(huì)在進行(xíng)二次訪問。
如下圖,是蘇甯易購河(hé)北地區(qū)出現的問題:
如圖中所示,頁面整個(gè)框架都在,但(dàn)就是沒有(yǒu)圖片,最終确定是由 DNS 劫持導緻的。
這裏的應對方法就是要建立完整的風控體(tǐ)系,在全國各地建設波測節點,做(zuò)整個(gè)請(qǐng)求圖片、頁面的記錄,并保存,如下圖:
當時(shí),河(hé)北地區(qū)用戶發出請(qǐng)求後,TCP 沒有(yǒu)辦法建立連接,使用 SSL 無法握手。原因是 DNS 劫持,被映射到非法的錯誤節點上(shàng)了。
應對方法還(hái)是我剛才說的降級手段,通(tōng)過 IP 判斷是河(hé)北移動的用戶就對 HTTPS 進行(xíng)降級成 HTTP,其他地方還(hái)繼續使用 HTTPS 策略。待當地運營商解決問題之後,再進行(xíng)恢複。
HTTPS 性能監控
如下圖,是蘇甯易購移動端的監控頁面:
HTTPS 灰度最重要的一個(gè)是做(zuò)好監控,必須要有(yǒu)一個(gè)監控覆蓋,要做(zuò)好灰度,每一步上(shàng)線時(shí)都要分析一下業務、性能、站(zhàn)內(nèi)站(zhàn)外投放,CPS 等數(shù)據。
一切數(shù)據分析都正常之後,再逐步擴大(dà)區(qū)域,按 APP 的版本和(hé)用戶級别進行(xíng)部署。
HTTPS 未來(lái)展望篇
這裏分享一個(gè)基于 UDP 的低(dī)時(shí)延的互聯網傳輸層協議:QUIC(Quick UDP Internet Connection)。
TCP/IP 協議族是互聯網的基礎,這個(gè) UDP 協議由谷歌(gē)提出,其用意是替代 TCP 協議。
這兩種協議,UDP 更為(wèi)輕量,錯誤校(xiào)驗也要少(shǎo)得(de)多(duō),但(dàn)可(kě)靠性方面要弱于 TCP。目前,針對 QUIC 協議,國外一些(xiē)公司在試用階段,強調的是既保證安全,又能保證握手不會(huì)對原來(lái)的傳輸造成影(yǐng)響,這也許是未來(lái)的發展方向。
作(zuò)者:朱羿全
來(lái)源:以上(shàng)內(nèi)容由編輯王雪燕根據朱羿全老師(shī)在 WOTA2017 “電(diàn)商大(dà)促背後的技(jì)術(shù)挑戰”專場(chǎng)的演講內(nèi)容整理(lǐ)。
HTTPS 的作(zuò)用是在會(huì)話(huà)層、表示層引入 TLS/SSL 握手協議,通(tōng)過數(shù)據加密、解密方式,來(lái)應對數(shù)據明(míng)文傳輸過程中遇到的問題,保障數(shù)據的完整性、一緻性,為(wèi)用戶帶來(lái)更安全的網絡體(tǐ)驗、更好的隐私保護。
然而,HTTPS 增加了 TLS/SSL 握手環節,再加上(shàng)應用數(shù)據傳輸需要經過對稱加密,對性能提出了更大(dà)的挑戰。
作(zuò)為(wèi)一個(gè)好的架構,一定要均衡安全和(hé)性能兩方面,如果讓天秤向任何一方傾斜過多(duō),都會(huì)影(yǐng)響最終的用戶體(tǐ)驗。
因此,為(wèi)了兼顧安全與性能,蘇甯的全站(zhàn) HTTPS 改造從 2015 年底開(kāi)始進行(xíng),曆時(shí)一年多(duō)時(shí)間(jiān),主要做(zuò)了系統 HTTPS 改造、HTTPS 性能優化和(hé) HTTPS 灰度上(shàng)線這三方面工作(zuò),讓用戶在 HTTPS 下訪問能夠獲得(de)極緻體(tǐ)驗成為(wèi)了可(kě)能。
全站(zhàn) HTTPS 方案概述
蘇甯易購從 2015 年開(kāi)始規劃做(zuò) HTTPS 相關的事情,當時(shí)可(kě)借鑒的資料非常少(shǎo),電(diàn)商類網站(zhàn)相關的 HTTPS 改造的詳盡案例更是難求。
如下圖,是蘇甯易購全站(zhàn)的 HTTPS 方案:
如圖中所示,整個(gè)方案分三步構建,分别是系統改造、性能優化和(hé)灰度上(shàng)線:
系統改造。原有(yǒu)系統想要支持 HTTPS,必須進行(xíng)改造,首先要建立 HTTPS 接入層,也就是開(kāi)通(tōng) 443 端口,讓所有(yǒu)的應用系統支持 HTTPS 訪問。
在此基礎上(shàng)做(zuò)頁面資源替換,解決當一個(gè) HTTPS 頁面出現 HTTP 請(qǐng)求時(shí)就會(huì)出現錯誤的問題。做(zuò)完這兩件事,CDN 上(shàng)證書(shū)的處理(lǐ)、HTTPS 測試方案等問題也就迎刃而解。
性能優化。做(zuò)系統改造,增加兩次 TLS 握手,必然會(huì)對性能造成一定的開(kāi)銷和(hé)損失,如何去彌補性能的損失,達到性能和(hé)安全兼顧呢?性能優化部分包含若幹優化點,下文會(huì)詳細展開(kāi)。
灰度上(shàng)線。這部分是時(shí)間(jiān)花(huā)費最多(duō)的,HTTPS 一步步上(shàng)線的過程中,踩坑最多(duō),其中部分是前面沒有(yǒu)發現的問題。
這證明(míng)不能一次性将整個(gè)全站(zhàn)、全地區(qū)、全用戶一次性堆成 HTTPS,可(kě)以根據流量所處的運營商和(hé)城市及用戶級别去做(zuò)灰度上(shàng)線。
HTTPS 方案之系統改造篇
01、HTTPS 接入層定義
系統改造的頭等大(dà)事是開(kāi)通(tōng) 443 端口,成熟的網絡系統會(huì)包含 CDN、硬件負載均衡、應用防火(huǒ)牆、Web 服務器(qì)、應用服務器(qì),最後到數(shù)據層。難道(dào)整個(gè)鏈路都要做(zuò) HTTPS?在每層都增加 SSL 握手消耗嗎?答(dá)案是否定的。
所以,應該盡早完成 SSL 握手,做(zuò) SSL 過程中首要考慮的是 HTTPS 接入層的定位。
如下圖,是蘇甯易購架構中 HTTPS 接入層的位置:
如圖中所示,我們把 HTTPS 接入層放在 CDN 和(hé)應用系統之間(jiān),采用四層+七層負載均衡的架構。
四層負載并不處理(lǐ) HTTPS 卸載,它的主要職責是做(zuò) TCP 的分發。在七層負載完成整個(gè) SSL 握手,而後面應用系統走 80 端口,這樣就相當于完成了 HTTPS 整個(gè)卸載的過程。
這樣做(zuò)的好處,一方面,系統應用層面不需要為(wèi) HTTPS 做(zuò)任何調整;另一方面,将來(lái)所有(yǒu) HTTPS 的調度、優化和(hé)配置都可(kě)以在接入層完成。
02、頁面資源替換
第一步,理(lǐ)解 Mixed Content
對于一個(gè)頁面而言,請(qǐng)求頁面的請(qǐng)求是用 HTTPS 加載,一旦內(nèi)部頁面元素有(yǒu) HTTP 的性質,這時(shí) RFC 标準裏就會(huì)出現一個(gè)錯誤,叫 Mixed Content(混淆錯誤)。
所以,如果要加載一個(gè)安全的 HTTPS 頁面,就不應該在其中混淆 HTTP 請(qǐng)求。
第二步,// 替換 http://
用 // 替換 http://,這樣就可(kě)以讓頁面所有(yǒu)的元素做(zuò)一個(gè)适配,去遵循原來(lái)的請(qǐng)求。
第三步,x-request-url 的定義和(hé)使用
當然,我們在//替換過程中也遇到了一些(xiē)坑。舉個(gè)例子,下圖是蘇甯易購單點登錄系統交互的過程:
如圖中所示,當用戶 authID 失效,發起請(qǐng)求 https://xxx.suning.com/authStatus 鑒權,接入層會(huì)對所有(yǒu)請(qǐng)求做(zuò)卸載,地址就會(huì)變成 HTTP。
進入業務系統做(zuò)鑒權的話(huà),Reponse 302 就會(huì)跳(tiào)轉到單點登錄系統。這時(shí)會(huì)将第二步的頁面記錄為(wèi)原始頁面,返回到用戶端,用戶去請(qǐng)求單點登錄系統,單點登錄系統完成鑒權以後,再回跳(tiào)時(shí),是 HTTP 地址,最終導緻用戶端 MixContent。
因此,我們引入 x-request-url 解決問題,如下圖:
所有(yǒu)原始請(qǐng)求協議都記錄在 x-request-url 中,如果業務系統鑒權,一定要遵循 x-request-url 記錄的協議,就可(kě)應對回跳(tiào)導緻的用戶端 Mix Content 問題。
03、App 原生(shēng)無法識别//的問題
出現浏覽器(qì)可(kě)以識别 //,但(dàn) App 原生(shēng)無法識别 // 的原因很(hěn)簡單,因為(wèi)浏覽器(qì)本身做(zuò)了适配。
當時(shí),蘇甯服務端有(yǒu)一個(gè)系統,專門(mén)提供一個(gè)接口,向各個(gè)端提供圖片。做(zuò)完 HTTPS 改造之後,PC 端和(hé)客戶端都沒有(yǒu)問題。但(dàn)是第二天,很(hěn)多(duō)用戶突然就不能加載圖片,原因是請(qǐng)求在 APP 原生(shēng)情況下沒法識别 //。
這裏的解決方法,隻能是客戶端開(kāi)發人(rén)員做(zuò)适配,下圖是 App 無法識别//的一個(gè)例子:
4、如何處理(lǐ)商用 CDN 上(shàng)的證書(shū)和(hé)私鑰?
CPN 證書(shū)的處理(lǐ)是大(dà)多(duō)數(shù)小(xiǎo)型互聯網企業都會(huì)遇到的問題。因為(wèi)這些(xiē)小(xiǎo)企業不像阿裏、京東可(kě)自建 CDN,蘇甯也是一樣。
蘇甯的 CDN 由自建和(hé)商用兩種組成,一旦使用商用 CDN,就會(huì)面臨 HTTPS 如何過去的問題。
企業隻要将私鑰給到第三方或廠商之後,在所有(yǒu)廠商的 CDN 服務器(qì)都沒辦法控制(zhì)。當有(yǒu)黑(hēi)客攻擊完廠商服務器(qì)後,加密已沒任何意義,因為(wèi)私鑰已經洩露。
如下圖,業界比較公認的應對方式分别是:雙證書(shū)的策略、四層加速和(hé) Keyless 解決方案。
雙證書(shū)的策略。它的思想很(hěn)簡單,相當于用戶到 CDN 端,提供的是 CDN 的證書(shū),做(zuò)加解密。從 CDN 到應用服務器(qì)端用的是應用自有(yǒu)的證書(shū)來(lái)做(zuò)加解密。
這樣的方式,可(kě)以保證應用端的密鑰不用提供給 CDN 廠商,但(dàn)根本的問題還(hái)是沒有(yǒu)解決,那(nà)就是 CDN 廠商的證書(shū)仍然有(yǒu)洩露的可(kě)能。如果洩露了,用戶端還(hái)是會(huì)受到影(yǐng)響。
四層加速。很(hěn)多(duō) CDN 廠商都有(yǒu)能力提供 TCP 加速,做(zuò)動态、還(hái)原和(hé)擇優等。CDN 廠商隻做(zuò)四層模式和(hé) TCP 代理(lǐ),不考慮請(qǐng)求緩存。
這樣就沒必要将證書(shū)暴露給 CDN 廠商,這種方式适用于動态回源請(qǐng)求,比如加入購物車(chē)、提交訂單、登錄等。
Keyless 解決方案。适用于金融,提供一台實時(shí)計(jì)算(suàn)的 Key Server 。
當 CDN 要用到私鑰時(shí),通(tōng)過加密通(tōng)道(dào)将必要的參數(shù)傳給 Key Server,由 Key Server 算(suàn)出結果并返回即可(kě)。
05、HTTPS 測試策略
當引入一個(gè)新的協議,如何進行(xíng)測試呢?主要步驟,如下圖:
源碼掃描。當開(kāi)發人(rén)員完成資源替換後,利用 Jenkins 遍曆代碼庫,shell 腳本掃描出 HTTP 鏈接。
對頁面爬蟲掃描。我們會(huì)寫一些(xiē)爬蟲腳本,對測試環境的鏈接進行(xíng)掃描。
測試環境驗證。自動化測試固然好,但(dàn)是主要核心流程還(hái)是需要手動覆蓋一遍,防止 HTTPS 對頁面加載出現未知影(yǐng)響。
如有(yǒu)些(xiē)頁面是用 HTTPS 去訪問,可(kě)能這個(gè)系統還(hái)不支持 HTTPS,必須要手動驗證。
線上(shàng)預發和(hé)引流測試。HTTPS 的改造版本發到線上(shàng)對用戶來(lái)講是沒有(yǒu)影(yǐng)響的,因為(wèi)用戶使用的還(hái)是 HTTP 流量。
可(kě)以選擇線上(shàng)預發的方式,預發驗證完畢後,通(tōng)過 301 的方式,将用戶的流量從 HTTP 切到 HTTPS,這個(gè)後面講灰度時(shí)還(hái)會(huì)深入講解。
另外,我們還(hái)引入了引流測試系統:
它的思路很(hěn)簡單,根據域名、用戶請(qǐng)求做(zuò)捕獲,将所有(yǒu)捕獲流量放到 Copy Server 中去擴大(dà),放大(dà)若幹倍,然後通(tōng)過 Sender 再發送回到系統中。
這樣的方式,可(kě)以通(tōng)過用戶的真實流量,來(lái)驗證 HTTPS 的功能性和(hé)性能影(yǐng)響有(yǒu)多(duō)大(dà)。
談如何優化 HTTPS 的性能之前,我們先來(lái)看看整個(gè) TLS 握手流程,如下圖:
如圖中所示,一個(gè)握手過程最壞的情況下,要分為(wèi)八個(gè)步驟:
發送 Syn 包到 Web 客戶端,收到并确認後,同時(shí)發送 SynAck 到服務器(qì),這時(shí)還(hái)是一個(gè) HTTP 的請(qǐng)求。
HTTP 轉換 HTTPS,需要做(zuò)一次 302 或者 301 跳(tiào)轉。
用戶再次發送 HTTPS 請(qǐng)求,做(zuò)一次 TCP 握手。
做(zuò) TLS 完全握手第一階段,Clienthello 到 Server hello。
當證書(shū)首次到客戶端,客戶端需要走驗證流程,做(zuò) CA 域名解析。
第二次,TLS 握手。
在線證書(shū)合法性校(xiào)驗的過程。
TLS 完全握手第二階段,底部灰色部分才是真正的數(shù)據通(tōng)訊。
蘇甯易購的全站(zhàn) HTTPS 方案在性能優化方面做(zuò)了很(hěn)多(duō)事情,如 HSTS、Session resume、Ocsp stapling 的合理(lǐ)使用,如客戶端 HTTPS 性能、HttpDNS 解決 DNS 攻擊劫持等優化。
01、HSTS 的合理(lǐ)使用
Web 安全協議 HSTS 的作(zuò)用是強制(zhì)客戶端(如浏覽器(qì))使用 HTTPS 與服務器(qì)創建連接。
優點是減少(shǎo) HTTP 做(zuò) 302 跳(tiào)轉的開(kāi)銷。302 跳(tiào)轉不僅暴露了用戶的訪問站(zhàn)點,也很(hěn)容易被中間(jiān)者劫持(降級劫持、中間(jiān)人(rén)攻擊),最重要是降低(dī)了訪問速度(影(yǐng)響性能)。
缺點是 HSTS 在 max-age 過期時(shí)間(jiān)內(nèi),在客戶端是強制(zhì) HTTPS 的,服務端無法控制(zhì)。
因此,當需要降級時(shí),HTTPS 無法及時(shí)切換到 HTTP。當然你(nǐ)也可(kě)以通(tōng)過手動動态去配置 max-age 的值,這樣可(kě)以通(tōng)過将 max-age 設置為(wèi) 0 來(lái)達到降級效果。
還(hái)有(yǒu) HSTS 是嚴格的 HTTPS,一旦網絡證書(shū)錯誤時(shí),網頁将直接無法訪問(用戶無法選擇忽視(shì))。
02、Session resume 的合理(lǐ)使用
當用戶端和(hé)客戶端、客戶端和(hé)服務端完成第一次 TLS 握手之後,第二次數(shù)據傳輸還(hái)需要 TLS 握手嗎?
這裏可(kě)以采用 Session 複用的方式。Session resume(會(huì)話(huà)複用),是 RFC 标準中早就定好的一個(gè)機制(zhì),HTTPS 最初發布時(shí)就已經涉及其中。
Session 複用有(yǒu) Session ID 和(hé) Session tickets 兩種方式,下圖是實現流程:
Session ID。使用 clienthello 中的 session ID 查詢服務端的 session cache,如果服務端有(yǒu)對應的緩存,則直接使用已有(yǒu)的 session 信息提前完成握手,稱為(wèi)簡化握手。
Session ID 是 TLS 協議的标準字段,市面上(shàng)的浏覽器(qì)全部都支持 Session ID。需要注意的是,單機多(duō)進程間(jiān)共享 ssl session 對集群環境是沒有(yǒu)意義的。
因此,在這裏需要實現多(duō)機共享 Session ID。可(kě)以放在 redis 中,nginx 提供了專門(mén)處理(lǐ) Session ID 的模塊 ssl_session_fetch_by_lua_block。
Session tickets。Session tickets 是會(huì)話(huà) ID 的一種補充,server 将session 信息加密成 ticket 發送給浏覽器(qì),浏覽器(qì)在後續握手請(qǐng)求時(shí)會(huì)發送 ticket,server 端如果能成功解密和(hé)處理(lǐ) ticket,就能完成簡化握手。
顯然,session ticket 的優點是不需要服務端消耗大(dà)量資源來(lái)存儲 session 內(nèi)容。但(dàn)是 session ticket 隻是 TLS 協議的一個(gè)擴展特性,目前的支持率不是很(hěn)廣泛,隻有(yǒu) 60% 左右。
還(hái)需要維護一個(gè)全局的 KEY 來(lái)加解密,需要考慮 KEY 的安全性和(hé)部署效率。
03、Ocsp stapling 的合理(lǐ)使用
Ocsp 全稱在線證書(shū)狀态檢查協議 (rfc6960),用來(lái)向 CA 站(zhàn)點查詢證書(shū)狀态,比如證書(shū)是否被撤銷,是否已經過期等。
通(tōng)常情況下,浏覽器(qì)使用 OCSP 協議發起查詢請(qǐng)求,CA 返回證書(shū)狀态內(nèi)容,然後浏覽器(qì)接受證書(shū)是否可(kě)信的狀态。
如下圖,是 Ocsp 實現流程:
這個(gè)過程非常消耗時(shí)間(jiān),因為(wèi) CA 站(zhàn)點有(yǒu)可(kě)能在國外,導緻網絡不穩定,RTT 也比較大(dà)。那(nà)有(yǒu)沒有(yǒu)辦法不直接向 CA 站(zhàn)點請(qǐng)求 OCSP 內(nèi)容呢?
ocsp stapling 就能實現這個(gè)功能。ocspstapling 的原理(lǐ)簡單來(lái)說是服務端代替客戶端完成 CA 校(xiào)驗證書(shū)的過程,節省用戶端的時(shí)間(jiān)開(kāi)銷。
就是當浏覽器(qì)發起 clienthello 時(shí)會(huì)攜帶一個(gè) certificate status request 的擴展,服務端看到這個(gè)擴展後将 OCSP 內(nèi)容直接返回給浏覽器(qì),完成證書(shū)狀态檢查。
由于浏覽器(qì)不需要直接向 CA 站(zhàn)點查詢證書(shū)狀态,這個(gè)功能對訪問速度的提升非常明(míng)顯。
HTTPS 方案之灰度上(shàng)線篇
灰度上(shàng)線可(kě)遵循灰度、降級和(hé)開(kāi)閉三大(dà)原則。灰度原則是指整個(gè)上(shàng)線過程要按區(qū)域、版本、用戶等級來(lái)進行(xíng)灰度,通(tōng)過灰度收集上(shàng)來(lái)的用戶數(shù)據來(lái)決定整個(gè)計(jì)劃的進行(xíng)。
降級原則保證每一步的操作(zuò)都是可(kě)逆可(kě)回滾的,即對擴展開(kāi)放,對修改關閉,這是可(kě)複用設計(jì)的基石。
01、HTTPS 開(kāi)關控制(zhì)
HTTPS 開(kāi)關控制(zhì)方面,蘇甯主要建設內(nèi)容管理(lǐ)、CDN、客戶端三大(dà)開(kāi)關:
內(nèi)容管理(lǐ)開(kāi)關。內(nèi)容管理(lǐ)開(kāi)關的作(zuò)用是保證所有(yǒu)運營維護的鏈接都可(kě)以被替換。
CDN 開(kāi)關。每個(gè)頁面,從 HTTP 到 HTTPS 都需要做(zuò) 301 跳(tiào)轉,這些(xiē)跳(tiào)轉都配置在 CDN 中。
客戶端開(kāi)關。就是移動加速 SDK 的開(kāi)關。
02、上(shàng)線過程中遇到的新問題
做(zuò)完開(kāi)關控制(zhì),在正式上(shàng)線的過程中,又遇到了一些(xiē)新問題如:Referrer、DNS 劫持、HTTPS 性能監控等。
Referrer
目前大(dà)部分浏覽器(qì),在發生(shēng)協議降級時(shí)默認不發送 Referrer 信息,最典型的場(chǎng)景就是從 HTTPS 頁面點鏈接跳(tiào)到 HTTP 網站(zhàn)時(shí),浏覽器(qì)并不會(huì)在請(qǐng)求頭中帶上(shàng) Referer 字段。當 Referrer 帶不過去,對大(dà)數(shù)據的影(yǐng)響非常大(dà),因為(wèi)沒辦法追溯流量來(lái)源。
針對現代的浏覽器(qì),這個(gè)問題可(kě)以通(tōng)過給頁面加上(shàng)下面這個(gè) meta 标簽來(lái)解決:
DNS 劫持
DNS 劫持是指非法破壞域名的解析過程導緻請(qǐng)求被解析到一個(gè)錯誤節點以達到某些(xiē)惡意目的。當我們使用 HTTP時(shí),DNS 異常可(kě)能還(hái)不會(huì)影(yǐng)響請(qǐng)求的功能性,但(dàn) HTTPS 因為(wèi)非法節點沒有(yǒu)證書(shū)和(hé)私鑰,肯定是無法響應了。
蘇甯的做(zuò)法的是通(tōng)過一些(xiē)波測監控 DNS 的正常,如下圖,我們監測到蘇甯中華特色館在某個(gè)地區(qū)有(yǒu)大(dà)量 DNS 解析異常。
出現 DNS 劫持,對用戶影(yǐng)響很(hěn)大(dà),一旦出現一次頁面打不開(kāi),用戶就會(huì)認為(wèi)這個(gè)頁面有(yǒu)問題,不會(huì)在進行(xíng)二次訪問。
如下圖,是蘇甯易購河(hé)北地區(qū)出現的問題:
如圖中所示,頁面整個(gè)框架都在,但(dàn)就是沒有(yǒu)圖片,最終确定是由 DNS 劫持導緻的。
這裏的應對方法就是要建立完整的風控體(tǐ)系,在全國各地建設波測節點,做(zuò)整個(gè)請(qǐng)求圖片、頁面的記錄,并保存,如下圖:
當時(shí),河(hé)北地區(qū)用戶發出請(qǐng)求後,TCP 沒有(yǒu)辦法建立連接,使用 SSL 無法握手。原因是 DNS 劫持,被映射到非法的錯誤節點上(shàng)了。
應對方法還(hái)是我剛才說的降級手段,通(tōng)過 IP 判斷是河(hé)北移動的用戶就對 HTTPS 進行(xíng)降級成 HTTP,其他地方還(hái)繼續使用 HTTPS 策略。待當地運營商解決問題之後,再進行(xíng)恢複。
HTTPS 性能監控
如下圖,是蘇甯易購移動端的監控頁面:
HTTPS 灰度最重要的一個(gè)是做(zuò)好監控,必須要有(yǒu)一個(gè)監控覆蓋,要做(zuò)好灰度,每一步上(shàng)線時(shí)都要分析一下業務、性能、站(zhàn)內(nèi)站(zhàn)外投放,CPS 等數(shù)據。
一切數(shù)據分析都正常之後,再逐步擴大(dà)區(qū)域,按 APP 的版本和(hé)用戶級别進行(xíng)部署。
HTTPS 未來(lái)展望篇
這裏分享一個(gè)基于 UDP 的低(dī)時(shí)延的互聯網傳輸層協議:QUIC(Quick UDP Internet Connection)。
TCP/IP 協議族是互聯網的基礎,這個(gè) UDP 協議由谷歌(gē)提出,其用意是替代 TCP 協議。
這兩種協議,UDP 更為(wèi)輕量,錯誤校(xiào)驗也要少(shǎo)得(de)多(duō),但(dàn)可(kě)靠性方面要弱于 TCP。目前,針對 QUIC 協議,國外一些(xiē)公司在試用階段,強調的是既保證安全,又能保證握手不會(huì)對原來(lái)的傳輸造成影(yǐng)響,這也許是未來(lái)的發展方向。
作(zuò)者:朱羿全
來(lái)源:以上(shàng)內(nèi)容由編輯王雪燕根據朱羿全老師(shī)在 WOTA2017 “電(diàn)商大(dà)促背後的技(jì)術(shù)挑戰”專場(chǎng)的演講內(nèi)容整理(lǐ)。
聯系我們
一切良好工作(zuò)的開(kāi)始,都需相互之間(jiān)的溝通(tōng)搭橋,歡迎咨詢。