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