【協議】HTTPS性能優化實踐
隨著iOS10限制HTTP以及Chrome對HTTP的警告提示,HTTPS技術以及優化支持逐漸受到各互聯網企業重視,本文《HTTPS性能優化實踐》根據羅成在2016ArchSummit全球架構師(北京)峰會上的演講整理而成。
ArchSummit即將在2018年7月6日深圳華僑城洲際酒店開幕,更多分享內容請瀏覽:鏈接
講師介紹:
羅成,騰訊資深研發工程師。目前主要負責騰訊stgw(騰訊安全雲網關)的相關工作,整體推進騰訊內部及騰訊公有雲,混合雲的七層負載均衡及全站HTTPS接入。對HTTPS,SPDY,HTTP2,QUIC等應用層協議、高性能伺服器技術、雲網路技術、用戶訪問速度、分散式文件傳輸等有較深的理解。
很榮幸來到ArchSummit全球架構師峰會現場和大家分享關於HTTPS的性能優化。首先自我介紹,我叫羅成,畢業之後加入百度,最開始做持續部署和文件傳輸方面的工作,然後換了工作內容,主要負責百度的統一接入和安全搜索的性能優化。現在在騰訊基礎架構部主要負責騰訊安全雲網關(STGW)的相關工作。STGW目前已經廣泛應用在騰訊內部的各大業務,以及騰訊公有雲、私有雲、混合雲等雲業務上。
我這次分享的內容主要是來自於我們HTTPS上具體的工作實踐,主要內容分以下三部分:- 計算性能的分析和優化;
- 無密鑰載入;
- 證書優化
為什麼66%的網站不支持HTTPS?
談優化之前我們先看背景和趨勢,大家也很清楚HTTPS是大勢所趨,Google、Facebook和國內諸多大型互聯網公司也已經支持HTTPS,然而這裡有兩點大家需要注意:
- iOS10的ATS政策(App Transport Security)要求2017年1月1日後所有在iOS App Store上架的App都需要支持HTTPS,否則無法上架;
- Google的Chrome瀏覽器54版本已經將HTTP的域名輸入框前增加「!」的提示,如下圖,所有的HTTP站點都會有這個標識。同樣在2017年1月1日後開始,Chrome瀏覽器會在用戶點擊「!」的提示符後將該網站不安全的信息顯示出來,只要涉及到登錄和搜集用戶數據的頁面,只要是HTTP的都會標註不安全,相信這也會加速HTTPS的推進。
HTTPS很安全,很古老也很成熟,為什麼一直到今天我們還有66%的網站不支持HTTPS呢?原因有兩點:
1. 慢,HTTPS未經任何優化的情況下要比HTTP慢幾百毫秒以上,特別在移動端可能要慢500毫秒以上,關於HTTPS慢和如何優化已經是一個非常系統和複雜的話題,由於時間的關係,本次分享就不做介紹了。但有一點可以肯定的是,HTTPS的訪問速度在經過優化之後是不會比HTTP慢;
2. 貴,特別在計算性能和伺服器成本方面。HTTPS為什麼會增加伺服器的成本?相信大家也都清楚HTTPS要額外計算,要頻繁地做加密和解密操作,幾乎每一個位元組都需要做加解密,這就產生了伺服器成本,但也有兩點大家可能並不清楚:
- HTTPS有哪些主要的計算環節,是不是每個計算環節計算量都一樣?
- 知道這些計算環節對CPU的影響,我們如何優化這些計算環節?
接下來我將介紹我們在這兩個問題上的探討。
HTTPS主要的計算環節
首先看HTTPS主要的計算環節,下圖是一個協議交互的簡要介紹圖,它的四種顏色分別代表4種不同的主要計算環節:
- 紅色環節是非對稱密鑰交換,通過客戶端和服務端不一致的信息協商出對稱的密鑰;
- 藍色環節是證書校驗,對證書的簽名進行校驗,確認網站的身份;
- 深綠色環節是對稱加解密,通過非對稱密鑰交換協商出對稱密鑰來進行加解密;
- 淺綠色環節是完整性校驗,不僅要加密還要防止內容被篡改,所以要進行自身的完整性校驗。
知道這些主要的計算環節之後,每一個計算環節對計算性能的影響分別是多少以及如何分析?這裡和大家分享我們計算性能的分析維度,主要分為三部分:演算法、協議和系統。
- 演算法,所謂的演算法其實是HTTPS所用到密碼學裡最基本的演算法,包括對稱加密、非對稱密鑰交換、簽名演算法、一致性校驗演算法等,對應的分析手段也很簡單:openssl speed;
- 協議,因為不同的協議版本和消息所對應使用的演算法是不一樣的,雖然演算法的性能很確定,但是和協議關聯起來它就不確定了。由於性能和協議相關,我們重點分析的是協議里完全握手的階段,我們會對完全握手的每個消息和每個函數進行時間的分析;
- 系統,比如我們使用Nginx和OpenSSL,我們會對它進行壓力測試,然後在高並發壓力環境下對熱點事件進行分析和優化。
接下來詳細介紹以上的分析維度,首先是對稱加密和一致性校驗演算法的測試分析,這個手段和工具(openssl speed)很簡單,我就不多介紹了。這裡總結一下:下圖中柱狀圖越高表示性能越好,可以看出性能最好的是AES-128-GCM,性能最差的是AES-256-CBC,但即使它性能最差,它也只需要47微秒就能處理4000個位元組,性能相比來說也還能接受。
接下來我們看密鑰交換和簽名演算法的測試,下表中Sign代表服務端進行的簽名,Verify指的是客戶端對簽名進行的校驗。我們關注一下紅色數字809,這代表使用RSA-2048位時,我們服務端1秒鐘只能處理809次,這已經是我們使用線上非常好的一款CPU進行測試的結果,事實上大部分機器1秒鐘只能處理三四百次,可以說性能非常差。
接下來是Verify校驗,能看出來我們使用Ecdsa(nistp256)時一秒鐘能處理7000多次,同樣這也是我們使用線上比較好的伺服器所測試的結果,由於Verify發生在客戶端,考慮到移動端手機的CPU是非常弱的,因此這裡一秒鐘可能只就能處理幾百次。
接下來看協議耗時的分析,這裡用ECDHE_RSA非對稱密鑰交換握手進行舉例,大家注意紅色ServerKeyExchange部分,它用了2400微秒(2.4毫秒),這是一個非常恐怖的概念,如果我們HTTPS請求每一次都需要進行完全握手處理,這意味著我們CPU一個核每秒最多只能處理400次多一點。
最後我們看熱點事件的分析,它也比較簡單,我們對系統進行壓力測試,用perf record對事件進行記錄,然後使用flame graph將它們可視化出來,最後看到一些相關數據和結果。
總結以上計算性能分析:
- 完全握手的性能不到普通HTTP性能的10%,如果說HTTP的性能是QPS 1萬,HTTPS可能只有幾百;
- 為什麼會這麼低呢?主要是RSA演算法,它對性能的影響佔了75%左右;
- ECC橢圓曲線如果使用最常用的ECDHE演算法,這部分約佔整體計算量的7%;
- 對稱加解密和MAC計算,它們對性能影響比較小,是微秒級別的。
有了這些分析結論,如何優化呢?我們總結了三個步驟:
- 首先第一步也是最簡單的一個優化策略,就是減少完全握手的發生,因為完全握手它非常消耗時間;
- 對於不能減少的完全握手,對於必須要發生的完全握手,對於需要直接消耗CPU進行的握手,我們使用代理計算;
- 對稱加密的優化;
簡化握手的原理以及實現
我們首先來看完全握手和簡化握手,這是TLS層的概念,我簡單說下簡化握手的兩個好處:
- 首先簡化握手相比完全握手要少一個RTT(網路交互),從完全握手大家可以看出來,它需要兩個握手交互才能進行第三步應用層的傳輸,而簡化握手只需要一個RTT就能進行應用層的數據傳輸;
- 完全握手有ServerKeyExchange的消息(紅色框部分),這個消息之前提過需要2.4毫秒,另外完全握手有Certificate證書的消息,而簡化握手並不需要。這也就是簡化握手第二個好處,它減少了計算量,它不需要CPU消耗太多時間。
既然簡化握手這麼好,我們如何實現?首先看協議層如何支持。TLS協議層有兩個策略可以實現,第一個是Session ID,Session ID由伺服器生成並返回給客戶端,客戶端再次發起SSL握手時會攜帶上Session ID,服務端拿到後會從自己的內存查找,如果找到便意味著客戶端之前已經發生過完全握手,是可以信任的,然後可以直接進行簡化握手。
第二個策略是Session Ticket,同樣它也是客戶端發起握手時會攜帶上的擴展,伺服器拿到Session Ticket後會對它進行解密,如果解密成功了就意味著它是值得信任的,從而可以進行簡化握手,直接傳輸應用層數據。
工程實現上會有什麼問題呢?現在最常用的Nginx+OpenSSL有兩個局限:
- Nginx只支持單機多進程間共享的Session Cache,假如我們所有接入用的是一台伺服器、一台Nginx的話,那ID生成和查找都在一起,肯定是可以命中的,但是我們大部分特別是流量比較大的接入環境都是多台機器接入。比如我們同一個TGW或者說LVS下面有多台Nginx,那麼第一台Nginx產生的ID返回給用戶,用戶可能隔了一個小時候之後再發起SSL握手,它攜帶上的Session ID肯定會隨機地落到某一台Nginx上面(比如落在第三台Nginx上),這樣肯定無法查找到之前的Session ID,無法進行簡化握手,這是第一個局限,即命中率會比較低;
- OpenSSL提供了一個Session Cache的callback可以回調,但是這個回調函數是同步的,而Nginx是完全非同步事件驅動的框架,如果Nginx調用這個callback進行網路查找,假如這個網路查找需要1毫秒,這意味著整體性能不會超過一千次。
我們如何進行改進?我們看第一個問題(Session Cache)的兩個改進方案:
1. IP Hash,這是最簡單的根據IP做Hash的負載均衡策略,相信大家對此都很清楚,這方案的好處是可以保證相同的IP用戶永遠都在同一台Nginx上面,Session Cache的命中率會提升,但是它有兩個缺點:
- 它容易導致熱點,我們有很多Net網關出口IP用戶的訪問量非常大,也就是說有一些IP請求非常大導致某一台機器負載不均衡;
- 用戶IP可能會經常變化,特別在移動端上,在Wi-Fi和4G環境下切換導致的IP變化同樣會使Session Cache的命中率降低。
2. 分散式緩存(分散式Session Cache),這是更優的方案,假如用戶開始發起握手,我們第一台Nginx生成ID會寫入到一個全局的比如redis緩存里,然後返回給用戶。用戶下一次發起握手的時候,假如他落到第三台Nginx上面,由於我們都是全局的Session Cache查找,這命中率一下就提升上來了。我們實現了這個方案,但暫時還沒有開源,在這裡可以給大家推薦兩個開源方案,大家有興趣可以了解一下。
- OpenResty,它提供了SSL Cache全局查找的指令;
- BoringSSL,這是Google fork OpenSSL的版本,它也在SSL層面上實現了非同步的Session Cache查找。
接下來我們看Session Ticket,由於Session Cache有個缺點是必須在服務端做緩存,會浪費很大內存,而Session Ticket有個好處是它不需要服務端做緩存,但同樣它也有個缺點:默認情況下比如三台Nginx各自的Session Ticket加解密密鑰是不同(這裡的密鑰是指Session Ticket的對稱加解密的密鑰而不是指證書對應的私鑰)。
舉個例子,比如第一台Nginx的Session Ticket用密鑰加密返回給用戶,用戶下一次再訪問落到第三台機器,你用第一台機器加密產生的密鑰用第三台的密鑰去解密肯定會失敗。這個問題很好解決,我們將所有的Nginx機器配置成同一個加解密的密鑰就可以了,這樣也能實現簡化握手。
我們看一下第三個方案:Self Session Ticket。Session ID和Session Cache都有一個共同點:Session基於內存,如果我們的App、瀏覽器或操作系統如果第一次啟動或重啟(或者瀏覽器的Tab關閉後又打開)都有可能導致Session ID和Session Ticket丟失,出於安全形度考慮,這情況下就必須要發起完全握手,怎麼解決呢?
如果這個App是我們完全自主、獨立自主開發,我們可以實現Self Session Ticket,我們將Ticket存儲在硬碟裡面,而不是在內存里。這顯然會帶來一定的安全風險,但是我們會做一些限制:
- Ticket存儲在App的私有路徑里,對非Root的手機是很難讀取到私有路徑的數據;
- 我們可以選擇對一些安全係數要求不是很高的業務開啟這個功能;
- 這個密鑰開關我們做到可以隨時控制。
綜上,即使這方案出現最危險的情況,其實是和HTTP方案是一樣的,它不會比HTTP方案安全性要差。
非同步代理計算的原理和實現
剛才提到的都是關於如何減少完全握手,提升簡化握手,但對很多的請求,比如說瀏覽器第一次啟動必須要經過完全握手,而且不是我們能夠自主控制的。對於這部分的內容,完全握手比例佔了至少30%以上,也就是說我們還有30%以上的請求必須要觸發CPU進行大量計算,對這部分怎麼解決呢?
我們的方案是非同步代理計算,主要是分三個步驟:
- 演算法分離,把最消耗CPU資源的演算法剝離出來,不讓它消耗本機的CPU資源;
- 代理計算,既然不消耗本機的CPU資源,我們可以使用硬體加速卡或者空閑的CPU資源來完成計算;
- 非同步執行,我把演算法分離出來交給計算集群去計算的時候,這個過程是非同步的,我不需要同步等待計算結果返回,這樣對我們性能提升也是非常有幫助的。
演算法分離
要分離哪些演算法?最主要是密鑰交換演算法(非對稱密鑰交換演算法),密鑰交換演算法最常用的是三類:- RSA
- ECDHE_RSA
- DHE_RSA
由於DHE_RSA是非常消耗性能的,這個方法也不安全,所以我們線上並沒有採用。目前使用最多的是ECDHE_RSA,考慮到兼容性的問題時使用了RSA。
RSA和ECDHE_RSA為什麼會消耗CPU資源?RSA主要是對客戶端發回來的pre_master_secret進行解密,它消耗CPU資源的過程是私鑰解密的計算;而ECDHE_RSA則有兩個步驟:
- 生成ECC橢圓曲線的公鑰和幾個重要的參數;
- 對這幾個參數進行簽名,客戶端要確保參數是我服務端發過來的,就是通過RSA的簽名來保證。
RSA簽名為什麼消耗CPU呢?RSA簽名同樣有兩個步驟:
- 首先它通過SHA1進行Hash計算;
- 對Hash結果進行私鑰加密,也就是最終消耗CPU的過程是私鑰解密和私鑰加密的計算。這兩個計算為什麼消耗CPU?看下圖公式,如果e或者d這個指數是一個接近2的2048次方的天文數字,那就非常消耗CPU。這也就是RSA演算法為什麼消耗CPU的最直接的數學解釋。
我們再看一下協議層面我們該如何實現分離。同樣以ECDHE_RSA為例,由於使用了ECC參數和RSA簽名,之前提到的ServerKeyExchange這個消息用了2.4毫秒,我們需要對這個消息進行分離,將一步操作拆成多個步驟。
我們再看一下RSA密鑰交換的分離,RSA非對稱密鑰交換演算法不需要ServerKeyExchange的消息,但需要對Client發過來的ClientKeyExchange進行解密的操作,也就是最消耗演算法的過程是RSA解密的地方,我們需要對這個步驟進行分離。
非同步代理計算——架構
以上是演算法層面包括協議層面進行的分離。接下來解釋工程實現上的架構,下圖左部分是最常用最簡單的配置,比如我們配置好Nginx+OpenSSL,然後把證書和私鑰放上去,把443埠打開,就能用上HTTPS了,但這裡消耗的都是本機的CPU資源,這裡面就會性能很差。
我們看非同步硬體加速卡代理計算的模型,用戶發起HTTPS握手,涉及到私鑰計算(比如ServerKeyExchange和對ClientKeyExchange解密)的時候,我們會把ECC的參數剝離出來發送給我們的計算集群,發送出去同時立馬非同步返回,又可以接受其他用戶的請求,不需要等待。
計算集群計算完了以後,我們會把計算結果返回給比如Nginx,Nginx又觸發最初的用戶場景,從而完成HTTPS的握手,這是一個大概的交互流程。
這裡面需要注意的是,我們不僅僅可以使用SSL硬體加速卡,還可以使用線上的空閑CPU資源,比如CPU比較空閑的存儲集群,如果硬體加速卡出現故障,我們可以直接把卡拔掉,可以用硬體加速卡集群上的CPU資源來做計算。我們對演算法的解耦是非常純粹的,和協議、證書沒有任何關係,我們只做RSA的計算,不管哪一邊進行升級,只要RSA演算法還是安全的,我們的協議就十分穩定,我們的維護成本也非常低。
非同步代理計算——工程實現
我們看一下工程實現,像Nginx需要事件框架進行修改來實現OpenSSL Nginx計算集群交互,通過模塊是無法實現的,儘管Nginx模塊機制非常強大豐富,但是它在HTTP頭部數據解析完成之後才能介入處理,但SSL握手只有進行SSL握手完之後才能進行應用層的數據傳輸,也就是說在進行SSL握手的時候,它沒有任何HTTP的數據,這時候模塊是沒辦法介入處理的,必須對事件框架進行修改。
關於OpenSSL,需要對OpenSSL的協議棧進行修改,主要涉及到s3_srvr.c這個文件,這個文件主要是實現OpenSSL握手的協議棧,這裡介紹一個開源方案:OpenSSL1.1.0,它已經支持了非同步事件,同樣還是需要修改Nginx才能實現非同步。性能也很強大,純ECDHE_RSA性能相比本機能夠提升3.5倍,而且解耦做得非常好。
ECC橢圓曲線的優化
剛才提到的一系列都是針對完全握手、簡化握手的介紹。接下來看對ECC橢圓曲線的優化,這裡說的優化不是針對演算法本身進行的優化,而是使用OpenSSL的官方版本過程中需要注意的地方。
盡量使用NIST P-256這條曲線,這條曲線是Intel幾個工程師在2013年進行的優化,性能提升了4倍。通常來講密鑰越大,性能肯定越差,比如RSA-2048肯定比1024要慢4倍左右,P-256曲線看上去應該比P-224要慢,但是實際上P-256曲線比P-224性能高了4倍,正是因為經過了一系列的優化。
另外需要注意的是OpenSSL的版本,這個優化特性只是在1.0.1L之後才加入的,下圖表格中OpenSSL的1.0.1e版本ecdh(nistp256)的性能只有2548,而OpenSSL的1.1.0b版本ecdh(nistp256)性能能達到10271,提高了4倍。
對稱加密演算法的優化
我們再看一下對稱加密演算法的優化,對稱加密主要分兩塊:
- 塊式對稱加密演算法,根據剛才OpenSpeed跑的結果也能發現AES-GCM性能最高,建議大家使用。AES-NI同樣是Intel CPU提供的硬體加速指令,這個指令相比不開啟的CPU性能要提升5倍左右,現在市面上2010年之後的Intel CPU都是支持的,但需要注意如果要直接使用AES對稱加解密,一定要使用OpenSSL封裝的EVP_EncryptInit_ex函數,而不是用最底層的AES_encrypt(儘管它很好記也很好用),默認的AES_encrypt函數是不會用硬體加速指令的,因此性能會很差;
- 流式對稱加密演算法。Chacha20-Poly1305是由Google專門針對移動端CPU優化的流式對稱加密演算法,它的性能相比普通演算法要提高3倍。但Chacha20演算法只適用於稍微低端、且不支持AES-NI指令的手機才能提高3倍,舉個例子,例如iPhone支持AES-NI,但它的性能還是會比AES-GCM要差的。
RC4、SSL3.0已經不安全了,也徹底退出了歷史舞台,但我們還有很多客戶端只支持SSL3.0,比如IE6,比如WindowsXP的一些客戶端和瀏覽器,我們的業務方仍需要支持這些業務,因此我們就必須支持SSL3.0,那如何支持呢?
首先SSL3.0為什麼不安全?主要是兩點:
- SSL3.0存在AES-CBC的緩存Poodle漏洞;
- RC4存在Bios偏移的漏洞;
這兩個漏洞哪個更嚴重?Poodle漏洞會更嚴重一些,於是開啟SSL3.0的話我們只支持RC4,這是第一點安全性的考慮,其次RC4的演算法性能要比AES-CBC要高,比如業務方一定要支持WindowsXP和IE6的話,優先使用RC4。
無密鑰載入
我們再看無密鑰載入,無密鑰載入的背景是這樣的,HTTPS證書和私鑰,私鑰是HTTPS安全的根本,如果私鑰被泄露了,那麼意味著你的HTTPS是沒有安全性可言,如果泄露了,只能撤銷證書,重新生成私鑰。
而且我們大部分使用HTTPS的場景都是將私鑰和證書同機部署在比如Nginx上面,然後私鑰保存在硬碟,這其實有安全風險的。比如說我們有很多兼容的大客戶,他使用了證書和私鑰,但是他的業務可能分散在幾個雲,或者幾個CDN上,他就會擔心私鑰如果泄露了怎麼辦?
我們因此設計了一個無密鑰載入的方案,我們先看普通的HTTPS流程,用戶發起HTTPS,到達騰訊雲,到達STGW,我們直接調用私鑰完成計算,完成HTTPS的握手,然後卸載,然後將HTTPS傳遞給業務。這是最普通的流程,會有一定的安全風險。
再看一下無密鑰載入流程,什麼是無密鑰呢?比如騰訊雲,我們接收的伺服器不需要部署私鑰,我們私鑰是完全放在客戶的物理伺服器上面,為了保證私鑰的安全,客戶甚至可以把這個物理伺服器放在家裡。
正常的接收流程是這樣的,我們用戶到達HTTPS握手,到達STGW,然後涉及到私鑰計算的時候,我們會把請求以及和私鑰相關的參數,封裝成一個非同步請求發給騰訊雲客戶的物理伺服器,然後物理伺服器會調用私鑰進行相關計算,再把計算結果返回給騰訊雲伺服器,完成HTTPS卸載。
整個交互流程中,STGW或者說騰訊雲和私鑰沒有任何的接觸,私鑰是客戶自己才擁有。這就是我們無密鑰載入的一個簡單的介紹。當然具體的流程或者實現,其實跟我剛才提到的非同步代理計算有點類似,包括協議方面。
證書優化
接下來看證書的優化。如果是個人用戶,向大家推薦Lets Encrypt,它是免費開源的CA證書頒發機構,它的優點就是免費開源,開源最大的好處就是可以對協議對整個交互流程都很清楚,支持Debug。它還有一個優點是能支持自動部署,它提供幾個工具運行幾分鐘就可以把證書申請下來。
但它也有缺點,第一,它只是低級別即域名級別的證書申請,它只對域名的有效性進行校驗,你能擁有這個域名就可以給你頒發證書,這就有安全風險了,假如我對域名進行劫持,我就可以冒名申請別人的證書。
另外兼容性也會比較差,像PC端Chrome訪問沒有任何問題,但我們用Android7.0去訪問就有可能出現問題,因為CA支持和更新並不及時,因此就有兼容性的風險,所以推薦個人用戶使用。
對於企業用戶,建議大家使用EV和OV級別的,因為它會需要你證書的機構、你的地址、法人信息、營業執照、在工商局的認證等信息,才確保只有你才能申請這個證書。
這是雲的優勢,申請很簡單,一鍵式申請,不需要你自己生成私鑰,也不需要生成證書的申請文件。這是騰訊雲證書簡單的說明。我們還有一個動作,在跟最大的證書廠商進行合作接觸,我們會實現自己更低成本的自主品牌證書的頒發,這樣的話證書會更加便宜,下圖是騰訊雲上面的介紹。
我們看一下證書籤名的選擇,我們最後使用了RSA,還使用ECDSA,這兩個是最主流最常用的簽名類型。
RSA的好處是兼容性好、歷史悠久,所有的客戶端都支持,因為它演算法已經存在40年了,缺點就是之前提到的代理計算,RSA需要私鑰進行計算,服務端需要加密解密性能會比較差。
ECDSA,優點就是服務端的性能好一點,P-256隻需要256位的輸出域就能實現和2048位長度同樣的安全性,它的安全性更高,服務端計算性能要好,但是客戶端的性能要差。使用ECDSA P-256客戶端的計算量要比RSA要大,RSA的公鑰的數字非常小,只有65537,而ECDSA的客戶端公鑰長度很大,計算性要差很多,特別是手機計算性能要弱。
ECDSA的缺點就是兼容性差,比如說WindowsXP不支持。具體可以看下圖的系統支持情況,這裡面其實由於RSA和ECDSA這兩個完全不同類型的證書,服務端其實可以同時支持,當然成本可能會稍微增加一些。目前使用ECDSA的還是多一些的。
最後看一下SHA1和SHA256,SHA1不安全,像Google和Microsoft已經宣布放棄SHA1,如果你使用SHA1證書就訪問不了。
SHA2兼容性比較差,比如WindowsXP不支持SHA2證書,但對於需要支持WindowsXP的業務來說如何兼容呢?我們觀察到一個特性:不支持SNI的客戶端也不支持SHA2。
SNI是TLS的一個特性和擴展,發起client hello的時候,它會攜帶上一個域名的信息,在握手的時候告訴服務端要訪問哪一個域名(Server Name Indicator),雖然從協議或者從原理的角度來講沒有任何的必然的關係,但這個現象給我們一個啟發:我們通過服務端配置能夠解決這個兼容性的問題。
同樣以Nginx和OpenSSL舉例,假如說客戶端1不支持SNI,只支持SHA1,客戶端2是新的系統支持SNI。我們配置配兩張證書,第一張證書我們同樣都是接403埠和兩個不同的Server,證書1放在前面,證書2支持SHA2放在後面。
當客戶端1發起請求的時候,由於它不支持SNI,所以默認會返回第一張證書(第一張證書是支持SHA1的),這樣不支持SNI也不支持SHA2的客戶端1兼容性沒有問題。
客戶端2發起請求的時候,攜帶了SNI,由於有SNI和域名信息,服務端會挑選有域名的信息SHA2返回給客戶端,實現SHA2的兼容。
最後是我對於HTTPS發展的簡單的概括和理解:
- 更廣。它會越來越流行,以後會成為互聯網的標配。HTTP2作為下一代的協議,主流實現像ChromeFireFox都是強制使用HTTPS的。ATS也強制使用HTTPS,Chrome2017年也會將HTTP標識為不安全;
- 更快。這裡涉及到訪問速度的優化,TLS1.3是革命性飛躍式的TLS協議,可以認為是TLS2.0,它相比1.2有非常大的變化,最大的變化有完全握手,它只需要一個RTT,而簡化握手不需要RTT,也就是應用層數據不需要握手直接可以完成數據的傳輸,另外QUIC解決HTTPS協議的性能問題,TLS協議以後也會越來越快,大家不用擔心訪問速度的問題;
- 更強。密鑰長度越來越大,加密強度會越來越強,隨著客戶端和硬體的發展,CPU加解密的性能也會越來越強;
- 更開放。之前提到類似Lets Encrypt的免費開源方案,以後也會成為越來越流行的方案。
以上是HTTPS的性能優化,謝謝大家!
推薦閱讀:
※【DevOps】阿里微服務之殤及分散式鏈路追蹤技術原理
※年度盤點(三) | 2016 年十大架構師必讀好文
※讀懂這100篇論文,你也能成為大數據專家
※【原創】雲時代的領航員--解決方案架構師職位說明