為什么超過百分之六十的網(wǎng)站不支持HTTPS?
HTTPS很安全,很古老也很成熟,為什么一直到今天我們還有66%的網(wǎng)站不支持HTTPS呢?原因有兩點:
1、慢,HTTPS未經(jīng)任何優(yōu)化的情況下要比HTTP慢幾百毫秒以上,特別在移動端可能要慢500毫秒以上,關(guān)于HTTPS慢和如何優(yōu)化已經(jīng)是一個非常系統(tǒng)和復(fù)雜的話題,由于時間的關(guān)系,本次分享就不做介紹了。但有一點可以肯定的是,HTTPS的訪問速度在經(jīng)過優(yōu)化之后是不會比HTTP慢;
2、貴,特別在計算性能和服務(wù)器成本方面。HTTPS為什么會增加服務(wù)器的成本?相信大家也都清楚HTTPS要額外計算,要頻繁地做加密和解密操作,幾乎每一個字節(jié)都需要做加解密,這就產(chǎn)生了服務(wù)器成本,但也有兩點大家可能并不清楚:
大家也很清楚HTTPS是大勢所趨,Google、Facebook和國內(nèi)諸多互聯(lián)網(wǎng)公司也已經(jīng)支持HTTPS,然而這里有兩點大家需要注意:
一、iOS10的ATS政策(App Transport Security)要求2017年1月1日后所有在iOS App Store上架的App都需要支持HTTPS,否則無法上架;
二、Google的Chrome瀏覽器54版本已經(jīng)將HTTP的域名輸入框前增加“!”的提示,如下圖,所有的HTTP站點都會有這個標識。同樣在2017年1月1日后開始,Chrome瀏覽器會在用戶點擊“!”的提示符后將該網(wǎng)站不安全的信息顯示出來,只要涉及到登錄和搜集用戶數(shù)據(jù)的頁面,只要是HTTP的都會標注不安全,相信這也會加速HTTPS的推進。
HTTPS主要的計算環(huán)節(jié)
首先看HTTPS主要的計算環(huán)節(jié),下圖是一個協(xié)議交互的簡要介紹圖,它的四種顏色分別代表4種不同的主要計算環(huán)節(jié):
紅色環(huán)節(jié)是非對稱密鑰交換,通過客戶端和服務(wù)端不一致的信息協(xié)商出對稱的密鑰;
藍色環(huán)節(jié)是證書校驗,對證書的簽名進行校驗,確認網(wǎng)站的身份;
深綠色環(huán)節(jié)是對稱加解密,通過非對稱密鑰交換協(xié)商出對稱密鑰來進行加解密;
淺綠色環(huán)節(jié)是完整性校驗,不僅要加密還要防止內(nèi)容被篡改,所以要進行自身的完整性校驗。
知道這些主要的計算環(huán)節(jié)之后,每一個計算環(huán)節(jié)對計算性能的影響分別是多少以及如何分析?這里和大家分享我們計算性能的分析維度,主要分為三部分:算法、協(xié)議和系統(tǒng)。
算法:
所謂的算法其實是HTTPS所用到密碼學(xué)里最基本的算法,包括對稱加密、非對稱密鑰交換、簽名算法、一致性校驗算法等,對應(yīng)的分析手段也很簡單:openssl speed; 協(xié)議:因為不同的協(xié)議版本和消息所對應(yīng)使用的算法是不一樣的,雖然算法的性能很確定,但是和協(xié)議關(guān)聯(lián)起來它就不確定了。由于性能和協(xié)議相關(guān),我們重點分析的是協(xié)議里完全握手的階段,我們會對完全握手的每個消息和每個函數(shù)進行時間的分析; 系統(tǒng):比如我們使用Nginx和OpenSSL,我們會對它進行壓力測試,然后在高并發(fā)壓力環(huán)境下對熱點事件進行分析和優(yōu)化。 最后我們看熱點事件的分析,它也比較簡單,我們對系統(tǒng)進行壓力測試,用perf record對事件進行記錄,然后使用flame graph將它們可視化出來,最后看到一些相關(guān)數(shù)據(jù)和結(jié)果。
1、總結(jié)以上計算性能分析:
2、完全握手的性能不到普通HTTP性能的10%,如果說HTTP的性能是QPS 1萬,HTTPS可能只有幾百;
3、為什么會這么低呢?主要是RSA算法,它對性能的影響占了75%左右;
4、ECC橢圓曲線如果使用最常用的ECDHE算法,這部分約占整體計算量的7%;
5、對稱加解密和MAC計算,它們對性能影響比較小,是微秒級別的。
有了這些分析結(jié)論,如何優(yōu)化呢?我們總結(jié)了三個步驟:
首先第一步也是最簡單的一個優(yōu)化策略,就是減少完全握手的發(fā)生,因為完全握手它非常消耗時間;
對于不能減少的完全握手,對于必須要發(fā)生的完全握手,對于需要直接消耗CPU進行的握手,我們使用代理計算;
對稱加密的優(yōu)化評論;
簡化握手的原理以及實現(xiàn)
我們首先來看完全握手和簡化握手,這是TLS層的概念,我簡單說下簡化握手的兩個好處:
首先簡化握手相比完全握手要少一個RTT(網(wǎng)絡(luò)交互),從完全握手大家可以看出來,它需要兩個握手交互才能進行第三步應(yīng)用層的傳輸,而簡化握手只需要一個RTT就能進行應(yīng)用層的數(shù)據(jù)傳輸;
完全握手有ServerKeyExchange的消息(紅色框部分),這個消息之前提過需要2.4毫秒,另外完全握手有Certificate證書的消息,而簡化握手并不需要。這也就是簡化握手第二個好處,它減少了計算量,它不需要CPU消耗太多時間。
既然簡化握手這么好,我們?nèi)绾螌崿F(xiàn)?首先看協(xié)議層如何支持。TLS協(xié)議層有兩個策略可以實現(xiàn),第一個是Session ID,Session ID由服務(wù)器生成并返回給客戶端,客戶端再次發(fā)起SSL握手時會攜帶上Session ID,服務(wù)端拿到后會從自己的內(nèi)存查找,如果找到便意味著客戶端之前已經(jīng)發(fā)生過完全握手,是可以信任的,然后可以直接進行簡化握手。
第二個策略是Session Ticket,同樣它也是客戶端發(fā)起握手時會攜帶上的擴展,服務(wù)器拿到Session Ticket后會對它進行解密,如果解密成功了就意味著它是值得信任的,從而可以進行簡化握手,直接傳輸應(yīng)用層數(shù)據(jù)。
工程實現(xiàn)上會有什么問題呢?現(xiàn)在最常用的Nginx+OpenSSL有兩個局限:
Nginx只支持單機多進程間共享的Session Cache,假如我們所有接入用的是一臺服務(wù)器、一臺Nginx的話,那ID生成和查找都在一起,肯定是可以命中的,但是我們大部分特別是流量比較大的接入環(huán)境都是多臺機器接入。比如我們同一個TGW或者說LVS下面有多臺Nginx,那么第一臺Nginx產(chǎn)生的ID返回給用戶,用戶可能隔了一個小時候之后再發(fā)起SSL握手,它攜帶上的Session ID肯定會隨機地落到某一臺Nginx上面(比如落在第三臺Nginx上),這樣肯定無法查找到之前的Session ID,無法進行簡化握手,這是第一個局限,即命中率會比較低;
OpenSSL提供了一個Session Cache的callback可以回調(diào),但是這個回調(diào)函數(shù)是同步的,而Nginx是完全異步事件驅(qū)動的框架,如果Nginx調(diào)用這個callback進行網(wǎng)絡(luò)查找,假如這個網(wǎng)絡(luò)查找需要1毫秒,這意味著整體性能不會超過一千次。