SSL協議最初是在Netscape瀏覽器中應用,用來保證經過Web進行電子商務交易的安全性,電子商務的安全性要求採用加密技術來保護客戶的我的資料,以及認證用戶,保證數據完整性,以確保交易安全。爲了實現這一目標,SSL協議在應用層實現,直接在TCP層之上(
圖4-1 ),使得在它上面的協議(HTTP,電子郵件,即時通信,和許多其餘應用)在網絡操通訊時,操做不變,同時提供通訊安全。html
若是正確的使用SSL,第三方只能推斷鏈接的兩端地址、加密類型,以及數據頻率和發送的大概數據量,但沒法讀取或修改任何實際數據。web
圖4-1 傳輸層安全(TLS)算法
當SSL協議被IETF標準化時,它被改名爲傳輸層安全(TLS)。許多人常常TLS和SSL名稱互換使用,但在技術上,它們是不一樣的,由於各自描述了不一樣版本的協議。瀏覽器
SSL 2.0是第一個公開發布版本的協議,但因爲發現了一些安全漏洞,它很快就被SSL 3.0取代。因爲SSL協議是Netscape專有的協議,IETF制定了一個新的標準規範協議(RFC 2246),被稱爲TLS 1.0,最終升級到了TLS 3.0。緩存
|
TLS和SSL 3.0之間的差異不是很是大,但仍是有一些差異的,在TLS 1.0和SSL 3.0之間不能進行互操做。安全 |
|
|
-- TLS協議 - RFC 2246服務器 |
TLS1.0在1999年1月正式發佈,隨後兩個新的版本被髮布,TLS1.1在2006年4月發佈,TLS1.2在2008年8月發佈,主要解決了一些安全漏洞以及擴展協議能力。雖然SSL 3.0內部實現和後續TLS版本很是類似,許多客戶繼續支持支持SSL 3.0和TLS 1.0 - 我相信有很好的理由升級到較新的版本,以保護用戶免受已知的攻擊!cookie
TLS被設計成在一個可靠的傳輸協議如TCP之上運行。然而,它也被改編運行在數據報協議之上(如UDP)。RFC 6347中定義的數據報傳輸層安全(DTLS)協議就是基於TLS協議,在保留數據報的傳輸模式前提下,可以提供TLS相似的安全保證。網絡
TLS協議的目的是爲在其之上運行的全部應用提供三種服務:加密,身份認證,數據完整性。從技術上說,你不須要在瞭解任何細節的狀況下使用這三個服務。您可能只接受證書,而不驗證其真實性,但你應該清楚地意識到這樣作的安全風險和影響。在實際應用中,一個安全的Web應用程序通常都會應用這三個特性。session
加密
一種用來混淆從一臺計算機到另外一個計算機之間信息的機制
認證
一種對提供的身份信息檢驗其合法性的機制
完整性
一種偵測信息是否被篡改和僞造的機制
爲了創建一個安全的加密的數據通道,鏈接雙方必須協商後續的加密算法,以及加密密鑰。TLS協議制定了一個清晰的握手序列來進行這些交換,咱們將在「TLS握手」章節進行詳細討論
。TLS在實際中應用普遍的一個主要緣由是它巧妙的握手過程,握手過程使用了公共密鑰加密(也稱爲非對稱密鑰加密)技術,通訊雙方能夠在以前沒有任何消息交互的狀況下進行共享密鑰協商,並且密鑰的協商能夠在未加密的通道上執行。
做爲TLS握手的一部分,該協議還容許通訊的兩端互相驗證對方的身份。應用到瀏覽器中,這個認證機制,容許客戶端驗證服務器是他們聲稱的身份(例如你的銀行),而不是有人只是經過僞造的名稱或者IP地址 - 這驗證主要基於第三方證書頒發機構和信任鏈。此外,服務器還能夠選擇性地驗證客戶端的身份 - 例如,一個公司的代理服務器能夠驗證全部員工,每一個人均可以有本身的公司簽署的證書。
最後,除了用戶認證和加密外,TLS協議還提供了它本身的消息分片機制,且採用消息認證碼(MAC)對每個分片消息進行簽名。MAC算法是一個單向的哈希加密函數(一個很是高效的校驗碼),HASH函數密鑰由兩端進行協商。每當一個TLS記錄被髮送,生成的MAC值,將附加在該消息中,接收端採用相同的方法計算和驗證所發送的MAC值,以確保消息的完整性和真實性。
三種方式結合起來,就構成了web上安全通訊的基礎。全部現代的Web瀏覽器都提供了各類加密算法,可以用來驗證客戶端和服務器,透明地執行每一條消息的完整性檢查。
網絡代理,中間服務器,TLS,web上的新協議
HTTP的成功和可擴展性建立了一個充滿活力的生態系統,在這個生態系統中包含各類代理和中間服務器:高速緩存服務器,安全網關,web加速器,內容過濾器,和其餘許多服務器。在某些場景下,咱們都知道他們的存在(顯式代理),而在不少狀況下,這些代理對最終用戶是徹底透明的。
不幸的是,這些中間或者代理服務器也帶來了一些小問題:一些代理服務器在不能解析的狀況下可能只是轉發HTTP的擴展,可是有一些代理服務器卻盲目的去處理了數據,即便他們不該該處理。另外,一些安全服務器會錯誤的把正常流量當作惡意流量。
在實際應用中,若是不採用標準HTTP語義和80端口的作法,每每致使不可靠的網絡部署:某些客戶端不會有任何問題,而另外一些可能會失敗或者發生不可預知的行爲 - 例如,在同一客戶端可能在不一樣網絡之間的切換時可能出現不一樣的結果。
因爲這些狀況的存在,新的協議和HTTP擴展,譬如WebSocket,SPDY,其餘擴展,一般依賴於創建的HTTPS隧道,來繞過中間代理,並提供一個可靠的部署模型:加密隧道混淆了全部的數據,使中間服務器不可見。這解決了眼前的問題,但它有一個缺點就是是不可以充分利用中間服務器提供的服務,譬如:身份驗證,緩存,安全掃描,等等。
這就是爲何大多數的WebSocket指南會告訴你使用HTTPS來傳送數據到移動客戶端 - 緣由就是上面所述。隨着時間的推移,中間服務器逐步升級,其能夠識別出新的協議,HTTPS部署也將變得不那麼必要了 - 除非您的會話實際須要TLS提供的加密,身份認證,完整性校驗等功能!
在客戶端和服務器開始基於TLS進行應用程序數據交換以前,雙方必須先協商好加密的通訊隧道:客戶端和服務器必須協商好TLS協議的版本,加密套件,若有必要,還須要驗證證書。不幸的是,每個步驟都須要在客戶端和服務器之間進行數據交互,這將增長了TLS鏈接的延遲(
圖4-2 )。
圖4-2 TLS握手協議
圖4-2假設紐約和倫敦之間的單向傳播延遲爲28ms,在前面章節中討論的TCP鏈接的例子同樣-
見表1-1 。
0 ms |
TLS運行在TCP基礎之上,這意味着咱們必須首先完成TCP 三次握手「 ,這須要一個完整的來回交互(RTT)。 |
56 ms |
TCP鏈接創建後,客戶端發送一些協商信息,如TLS協議版本,支持的密碼套件的列表,和其餘TLS選項。 |
84 ms |
服務器挑選TLS協議版本,在加密套件列表中挑選一個密碼套件,附帶本身的證書,並將響應返回給客戶端。可選的,服務器也能夠發送對客戶端的證書認證請求和其餘TLS擴展參數。 |
112 ms |
假設雙方協商好一個共同的TLS版本和加密算法,客戶端使用服務器提供的證書,生成新的對稱密鑰,並用服務器的公鑰進行加密,並告訴服務器切換到加密通訊流程。到如今爲止,全部被交換的數據都是以明文方式傳輸,除了對稱密鑰外,它採用的是服務器端的公鑰加密。 |
140 ms |
服務器用本身的私鑰解密客戶端發過來的對稱密鑰,並經過驗證MAC檢查消息的完整性,並返回給客戶端一個加密的「Finished」的消息。 |
168 ms |
客戶端採用對稱密鑰解密消息,並驗證MAC,若是一切OK,加密隧道就創建好了。應用程序數據就能夠發送了。 |
一個新的TLS鏈接須要兩個往返「完整的握手」。或者,可使用「簡短握手」,這隻須要一個來回-參見「TLS會話恢復」 。
協商一個安全TLS通訊隧道是一個複雜的過程,很容易犯錯。好消息是,上述複雜的工做都已經由服務器和瀏覽器替咱們作了,全部咱們須要作的是提供和配置證書。
儘管瀏覽器和服務器替咱們完成了複雜的工做,當咱們的Web應用程序沒有必要進行加密通訊時,咱們須要牢記每TLS鏈接將須要額外的兩個TCP往返 - 在應用程序能夠進行交換數據前,這是一個比較長的延遲!若是管理的很差,經過TLS傳輸數據可能增長几百ms的延遲,固然不太可能達到上千ms的延遲。
公鑰加密 vs 對稱加密
公鑰加密僅用於會話建立TLS隧道的過程當中。服務器提供公鑰給客戶端,客戶端產生一個對稱密鑰,採用服務器的公鑰加密,加密後的對稱密鑰,返回給服務器。而後,服務器用本身的私鑰進行解密對稱密鑰。
使用由客戶端生成的共享密鑰的對稱密鑰加密法將其用於後續客戶端和服務器之間的全部通訊。這麼作的主要緣由是爲了提高性能 - 非對稱加密算法的計算複雜度高不少。想理解這個差別,若是您的計算機上安裝了OpenSSL,你能夠運行下面的測試:
須要注意的是兩次測試之間沒法直接對比:RSA測試經過對不一樣長度的密鑰進行一組數據進行測試,而AES性能測量的是每秒加密的字節數。儘管如此,它應該很容易地看到,推薦的1024或2048位密鑰長度的RSA運算(全TLS握手),可能成爲瓶頸。
確切的性能受使用的硬件,CPU核數量,TLS版本,服務器的配置,和其它因素的影響。不要受市場宣傳誤導,也不要相信過期的基準測試!始終在本身的硬件上作性能測試。
兩個網絡節點可能使用一個自定義的應用程序協議進行互相通訊。解決這個問題的方法之一是在肯定協議的前期,給它分配一個衆所周知的端口(例如,端口80用於HTTP,TLS的端口443),並配置全部客戶端和服務器使用它。然而,在實踐中,這是一個緩慢和不切實際的過程:每一個端口的分配必須批准,更糟的,防火牆及其餘中間服務器每每只容許使用80和443進行通訊。
結果是,爲了咱們自定義協議更加容易部署,咱們必須複用80或443端口,經過額外的機制來協商應用協議。80端口被保留用於HTTP,HTTP規範提供了一個特殊的Upgrade流程來完成這個目標。然而,使用Upgrade可能帶來額外的網絡往返延遲,並在實際應用中每每由於許多中間服務器的存在是不可靠的,- 參考「代理,中間服務器,TLS協議和網絡上的新協議「章節。
HTTP升級流程的一個例子能夠參考「高效的HTTP 2.0升級和發現」章節 。
解決的辦法是,使用端口443,這是保留給HTTPS會話(運行於TLS之上)。端到端的加密隧道使數據加密經過各類中間服務器,而不被篡改,這能夠快速和可靠的方式實現和部署任意的應用程序協議。然而,使用TLS解決了可靠性,咱們仍然須要一種方式來協商應用協議!
HTTPS會話,固然,複用了HTTP的升級機制來執行協商,可是這帶來了一個額外完整的往返延遲(RTT)。若是咱們把協議協商做爲TLS握手自己的一部分呢?
正如它的名字所暗示的,應用層協議談判(ALPN)是一個TLS擴展,支持在TLS握手( 圖4-2 )過程當中進行協議協商,從而省去經過HTTP升級流程所需的額外往返延遲。具體地,過程以下:
服務器可能只響應其中一個協議,若是它不支持任何客戶端要求的協議,那麼它可能選擇停止鏈接。其結果是,TLS握手完成後,安全隧道創建好了,客戶端和服務端也協商好了所使用的應用協議 - 它們能夠當即開始通訊。
ALPN節約了HTTP升級交換的必要性,節省了一個額外的往返延遲。然而,請注意,TLS握手自己依舊必須被執行,所以ALPN協商不會比採用HTTP升級流程創建的未加密的通道快。相反,它只是確保經過TLS進行應用協議協商不會更慢 。
NPN和ALPN的歷史關係
NPN(Next Protocol Negotiation)是一個TLS擴展,是Google提供的SPDY中的一部分,以實如今TLS握手中進行應用協議協商。聽起來是否是很熟悉?最終的結果是和ALPN功能至關。
ALPN是NPN擴展的修訂和IETF批准版本。在NPN中,服務器宣告它支持的協議,而後由客戶端選擇並確認協議。在ALPN,這個過程正好倒過來,客戶端宣稱其支持的協議,服務器選擇並確認協議。改變的理由是,ALPN能夠和其餘比較接近的協商標準保持最大程度的一致性。
換句話說,ALPN是NPN的繼任者,NPN已被棄用。依賴於NPN協商的客戶端和服務器必須進行升級,使用ALPN。
任意兩個TCP端之間均可以創建加密的TLS隧道:客戶端只須要知道對端的IP地址就能夠創建鏈接,並執行TLS握手。可是,若是服務器須要部署多個獨立的網站,每一個與本身的TLS證書,但使用同一個IP地址 - 請問如何處理?棘手的問題,答案是不行。
爲了解決上述問題,SNI(服務器名稱指示)擴展被引入到TLS協議中,它容許客戶端在握手開始指示他想要鏈接的主機名。服務器檢查SNI主機名,選擇適當的證書,並繼續握手。
TLS,HTTP和專用IP
TLS + SNI工做流程和HTTP的Host頭域宣告流程是相同的,客戶端在頭域中指示它要請求的Host:同一IP地址可能會部署許多不一樣domain,SNI和Host都是用來區分不一樣的Host或者Domain。
不幸的是,許多老的客戶端(例如,大多數在Windows XP上運行的IE瀏覽器,Android 2.2,和其餘一些瀏覽器)不支持SNI。所以,若是您須要爲這些老客戶提供TLS,那麼你可能須要爲每一個主機的專用IP地址。
完整的TLS握手須要額外延遲和計算,爲全部須要安全通訊的應用帶來了嚴重的性能損耗。爲了幫助減小一些性能損耗,TLS提供恢復機制,或多個鏈接之間共享相同的協商密鑰數據。
「會話標識符」(RFC 5246)恢復機制在SSL 2.0中首次被引入,它容許服務器在「ServerHello消息」中構建和發送一個32字節的會話標識符,做爲「ServerHello」消息的一部分。
在服務器內部,服務器維護一個會話ID和其對應的協商參數的緩存。反過來,客戶端也同時存儲會話ID信息,在後續的會話中,能夠在「ClientHello」消息中攜帶session ID信息,指示服務器它保存了session ID對應的密鑰和加密算法等信息,而且能夠重用這些信息。假設在客戶端和服務器都能在它們各自的緩存中找到共享的會話ID參數,那麼縮減的握手(
圖4-3 )就能夠進行了。不然,開始一個新的會話協商,這將產生一個新的會話ID。
圖4-3 縮減的TLS握手協議
藉助會話標識符,咱們可以減小一個完整的往返,以及用於協商的共享密鑰的公鑰加密算法開銷。這讓咱們能快速的創建安全鏈接,而不損失安全性。
在實際應用中,大多數Web應用程序試圖經過創建到同一個主機的多個鏈接並行獲取資源,這使得會話恢復成爲必不可少的一個優化項,其能夠減小延遲,計算成本。
大多數現代瀏覽器都會有意的等待第一TLS鏈接完成後,再打開到同一臺服務器的新鏈接:後續TLS鏈接,能夠重複使用的SSL會話參數,以免握手的延遲和損耗。
然而,「會話標識符」機制的一個限制就是要求服務器爲每一個客戶端建立和維護一個會話緩存。這會爲服務器上帶來幾個問題,對於一些天天同時幾萬,甚至幾百萬的單獨鏈接的服務器來講:因爲緩存session ID所須要的內存消耗將很是大,同時還有session ID清除策略的問題。這對一些流量大的網站來講不是一個簡單的任務,理想的狀況下,使用一個共享的TLS會話緩存能夠得到最佳性能。
上述問題沒有是不可能解決的,許多高流量的網站成功的使用了會話標識符。可是,對任何多服務主機的部署,會話標識符方案須要一些認真的思考和好的系統架構,以確保良好的的會話緩存。
爲了解決上面的會話緩存帶來的服務器部署問題,「Sesion Ticket」(RFC 5077)取代機制被引入,目標是消除服務器須要維護每一個客戶端的會話狀態緩存的要求。相反,若是客戶指示它支持Session Ticket,在TLS握手的最後一步中服務器將包含一個「New Session Ticket」信息,包含了一個加密通訊所須要的信息,這些數據採用一個只有服務器知道的密鑰進行加密。
這個Session Ticket由客戶端進行存儲,並能夠在隨後的一次會話中添加到 ClientHello消息的SessionTicket擴展中-所以,全部的會話信息只存儲在客戶端上,Session Ticket仍然是安全的,由於它是由只有服務器知道的密鑰加密的。
Session Identifiers和Session Ticket機制一般分別被稱爲「會話緩存」和「無狀態恢復」機制。無狀態恢復的主要改進是消除服務器端的會話緩存,從而簡化了部署,它要求客戶在每個新的會話開始時提供Session Ticket - 直到Ticket過時。
在實際應用中,在一組負載平衡服務器中部署Session Ticket,也須要仔細考慮:全部的服務器都必須用相同的會話密鑰,或者可能須要額外的機制,按期輪流在全部服務器上的共享密鑰。
身份驗證是創建每一個TLS鏈接一個重要的組成部分。畢竟,TLS能夠與任何端經過一個加密的隧道進行通訊,包括攻擊者,除非咱們能夠確信和咱們通訊的對方是可信任的,否則全部的加密工做都是無效的。要了解咱們如何驗證對方的身份,讓咱們來看看一個Alice和Bob之間簡單的身份驗證工做流程:
信任是上述通訊的一個重要組成部分。具體來講,公鑰加密算法容許咱們使用發送方的公鑰來驗證其用私鑰簽名的消息,但這個驗證是基於信任的基礎上。在上面的交換過程當中,Alice和Bob能夠親自交換他們的公鑰,由於他們互相瞭解對方,他們肯定他們的交換沒有被第三方冒名頂替 - 也許他們甚至經過另外一種方式來驗證他們的身份,祕密(物理)握手,經過他們已經創建的握手!
接下來,Alice從她從未見過的Charlie那裏接收到一條消息,但Charlie聲稱本身是Bob的朋友。事實上,Chralie爲了證實他是Bob的朋友,Charlie請求Bob用他的私鑰對本身的公鑰進行簽名,並在消息中附帶了這個簽名(
圖4-4 )。在這種狀況下,Alice首先檢查Bob對Charlie公鑰的簽名。她知道Bob的公鑰,所以她能夠確認Bob確實對Charlie的公鑰簽名了。由於她信任Bob對Charlie的簽名,她接受該消息,並対Charlie的消息進行相似完整性檢查,以確保它確實是從Charlie發送過來的。
圖4-4 Alice,Bob和Charlie的信任鏈
咱們剛纔所作的過程就是創建信任鏈:Alice信任Bob,Bob信任Charlie,信任被傳遞,Alice決定信任Charlie。只要信任鏈中沒有人被攻破,咱們可以構建和擴大信任的名單。
web和您的瀏覽器上的身份認證遵循了上面一樣的步驟。這時你可能會問:你的瀏覽器該信任誰,當你使用瀏覽器是該信任誰?這個問題至少有三個答案:
手動指定的用戶證書
每個瀏覽器和操做系統都提供了手動導入任何您信任的證書的機制。如何得到證書,並驗證其完整性徹底取決於你。
證書頒發機構
證書頒發機構(CA)是一個值得信賴的第三方的機構(全部者),其證書值得信任。
瀏覽器和操做系統
每一個操做系統和大多數瀏覽器都包含了知名的證書頒發機構的列表。所以,你也能夠信任這個軟件的供應商,提供並維護的信任列表。
在實際應用中,手動驗證爲每個網站的證書(儘管你能夠,若是你是這樣的傾向)是不切實際。所以,最多見的解決方案是藉助(
圖4-5 )證書頒發機構(CA)作這項工做 :在瀏覽器中指定哪些CA是可信任(根CA證書),CA負責驗證你訪問的每一個網站,並進行審覈,以確認這些證書沒有被濫用或受損害。若是任何網站違反了CA的證書的安全性規定,那麼CA有責任撤銷其證書。
圖4-5 CA數字證書籤發
基本上每個瀏覽器,均可以讓你檢查安全鏈接的信任鏈( 圖4-6 ) -一般是經過點擊URL旁邊的鎖形圖標。
圖4-6 igvita.com的證書信任鏈(谷歌瀏覽器,V25)
信任鏈中的錨點就是證書籤發機構的根證書,在上面的例子中就是是 StartCom Certification Authority。每個瀏覽器會預先置入一個受信任的證書頒發機構(「根證書」)列表,在上面的例子中,瀏覽器信任和可以驗證StartCom的根證書。所以,經過瀏覽器,瀏覽器供應商,StartCom證書頒發機構的信任傳遞鏈,咱們擴展到信任咱們訪問的站。
每個操做系統供應商和每個瀏覽器都提供了一個默認信任的證書頒發機構列表。若是你很好奇,你能夠經過搜索引擎搜索和查看這些清單。
在實踐中,有數百個知名的和受信任的證書頒發機構,這也是系統的一個大麻煩。大量的CA致使了對您的瀏覽器的信任鏈大面積潛在的攻擊。
偶爾證書的頒發機構可能須要撤銷或做廢證書,這可能因爲證書的私鑰被攻破了,證書頒發機構自己被攻破,或者其餘一些正常的緣由譬如證書替換、證書籤發機構發生變化,等等。爲了解決這個問題,證書自己包含了檢查是否已吊銷的邏輯(
圖4-7 )。所以,爲了確保信任鏈不會受到攻擊影響,每一個節點均可以檢查每一個證書的狀態,連同簽名。
圖4-7 CRL和OCSP(谷歌瀏覽器,V25爲igvita.com)
證書撤銷列表(CRL)是在RFC 5280中定義的,它制定了一個簡單的機制來檢查每一個證書的狀態:每一個證書頒發機構維護並按期發佈一份吊銷證書序列號列表。任何人想驗證一個證書,他能夠從證書頒發機構下載吊銷列表,並檢查序列號是否在吊銷列表中 - 若是找到,那麼證書已經被撤銷。
CRL文件自己能夠按期公佈,或在每次更新時都公佈,CRL文件能夠經過HTTP,或任何其餘文件傳輸協議傳輸。該名單也是由CA簽名,一般容許以指定的時間間隔緩存。在實際應用中,這個流程運行得很好,但也有一些場景CRL機制可能存在缺陷:
爲了解決CRL機制的一些缺陷,在線證書狀態協議(OCSP)在RFC 2560中被制定,它提供了一個實時執行證書狀態檢查的機制。不一樣於CRL,其包含了全部被撤銷序列號,而OCSP只須要客戶端傳進序列號,就能夠直接驗證證書鏈。
所以,OCSP機制消耗更少的帶寬,並可以提供實時驗證。然而,沒有任何機制是完美的!OCSP要求進行實時查詢也引入了幾個問題:
在實際應用中,CRL和OCSP機制是互補的,大多數證書機構同時提供兩種機制。
更重要的部分是客戶端的支持和行爲:一些瀏覽器發佈本身的CRL列表,另一些從CA中獲取CRL文件並緩存它。一樣,有些瀏覽器會進行實時的OCSP檢查,但當OCSP請求失敗時,瀏覽器的行爲又各自有一些區別。若是你好奇,能夠檢查一下您的瀏覽器和操做系統的證書吊銷設置!
TLS和下面的IP或TCP層比較起來沒有什麼本質不一樣,全部TLS會話內的數據交換採用了一個良好定義的協議(
圖4-8 )。TLS記錄協議主要用來識別TLS中消息的類型(經過「Content Type」字段的數據來識別握手,Alert或數據),以及每一個消息的完整性保護和驗證。
圖4-8 TLS記錄協議結構
一個傳輸數據的典型流程以下:
一旦上述步驟完成後,加密的數據被向下傳遞到TCP層進行傳輸。在接收端,採用反向相同的工做流程:使用協商的加密算法對數據進行解密,驗證MAC,提取的應用數據給應用層。
另外一個好消息,全部上述的處理都是TLS層自己處理,對大多數應用程序是徹底透明的。然而,TLS記錄協議引入了幾個你應該知道的影響:
應用程序應該挑選合適的TLS記錄大小,若是你能夠去設置,這也能夠是一個重要的優化。記錄過小致使分幀過多,容易產生較大的開銷,而記錄過大,則在TCP層須要從新分塊而後在接收端從新拼裝,數據才能夠被TLS層處理,並傳遞到您的應用層。
因爲網絡協議的分層架構,應用程序經過TLS和直接經過TCP運行對比,沒有什麼不一樣。所以,應用層基本上不用或者進行少許的修改,就能夠經過TLS傳輸數據。也就是說,「TCP優化」的最佳實踐徹底能夠用於TLS。
可是,你應該檢查TLS部署:如何以及在哪裏部署服務器,TLS記錄的大小和內存緩衝區大小,證書大小,是否支持縮減握手,等等。服務器上這些參數配置若是正確,可讓用戶體驗產生較大的積極影響,也能夠下降您的運營成本。
創建和維護一個加密的通道,通訊雙方都引入了額外的一些計算成本。具體來講,首先是「TLS握手」中使用的不對稱(公鑰)加密算法 。而後,一旦創建了共享密鑰的通訊通道後,後續數據都採用對稱密鑰來加密。
正如咱們前面提到的,公鑰加密與對稱密鑰加密相比,須要消耗更多的CPU計算,web流行早期,每每須要額外的硬件來執行「SSL負載分擔」。好消息是,這一切再也不須要。如今硬件已經發生了翻天覆地的變化,這些CPU運算已經變得微不足道了,之前須要額外硬件才能完成的運算,如今徹底能夠在CPU上直接完成了。譬如Facebook和Google這些大型公司,正爲數以百萬計的用戶提供TLS服務,全部必要的TLS協商和CPU運算都在普通的硬件中執行。
|
2010年1月,Gmail缺省狀況下采用HTTPS提供一切服務。此前,HTTPS只是做爲一個可選項,但如今咱們全部的用戶都使用HTTPS來保護他們的電子郵件安全。爲了作到這一點,咱們沒有部署額外的機器,也沒有部署特別的硬件。對咱們產品前置機來講,SSL / TLS帳戶的CPU的負載小於1%,每一個鏈接佔用不到10 KB的的內存,不到2%的網絡開銷。許多人認爲SSL / TLS須要花費大量的CPU運算時間,咱們但願上面的數字(首次公開),將有助於消除你們的誤解。 若是你如今中止往下閱讀,你只須要記住一件事:SSL / TLS不不屬於CPU消耗型操做。 |
|
|
- Adam Langley (Google) |
|
咱們已經使用硬件和軟件負載平衡器大規模的部署了TLS服務。咱們發現,目前基於軟件的TLS實現,徹底能夠運行在普通的CPU上,其速度已經足夠快的用來處理繁重的HTTPS流量負載了,無需藉助專用加密硬件。咱們全部HTTPS服務都是使用運行在普通硬件上的軟件。 |
|
|
- Doug Beaver (Facebook) |
儘管如此,「TLS會話恢復」等技術仍然是重要的優化,這將有助於下降計算成本和公共密鑰加密TLS握手帶來的延遲-你沒有必要去無謂增長你的CPU負荷,在沒有任何須要的前提下。
提及優化CPU負荷,咱們還須要確保SSL庫升級到最新的版本,並採用他們來創建你的Web服務器或代理服務器!例如,最近版本的OpenSSL取得了顯着的性能改進,沒準,你的系統默認的OpenSSL庫早已過期。
TLS鏈接的延遲,不管是新的鏈接或恢復鏈接,都是優化須要重點考慮的一個領域。首先,咱們前面描述過,每個TCP鏈接以「三次握手」開始 ,這須要一個完整的往返(SYN
/ SYN-ACK包)。接着, 是「TLS握手」,最多須要兩個額外的往返(RTT),或一個往返,若是使用「TLS會話恢復」 的話。
在最壞的狀況下,在任何應用程序交換數據以前,TCP和TLS鏈接過程須要三個完整的往返!以咱們前面的例子做參考,客戶端在在紐約,服務器在倫敦,一個完整的往返是56ms(
表1-1 ),這意味着一個完整的TCP和TLS創建至少有168ms的延遲,若是採用TLS會話恢復則至少有112ms的往返延遲。更糟的是,兩端之間的傳播延遲越高,TLS鏈接的延遲也是越大,56 ms絕對是一個很樂觀的數字!
由於TLS會話運行在TCP之上。「TCP優化」,的全部優化建議一樣也適用於TLS。若是TCP鏈接複用對於未加密傳輸來講是一個重要的考慮因素,那麼它對經過TLS進行數據傳輸的應用來講,一樣也是一個關鍵的優化
- 若是你能避免作握手,儘可能避免。若是你確實要執行握手操做,那麼你可能須要瞭解一下「提早終止」的技術。
正如咱們在第1章中討論的那樣,咱們不能指望減小數據包的傳播延遲,畢竟他們已是光速級了。然而,咱們可能沒法使咱們的包傳輸更快,但咱們可讓他們的傳輸更短的距離!提早終止是一個簡單的技術,將您的服務器更貼近用戶(
圖4-9 ),使每一個客戶端和服務器之間的往返延遲成本降到最低。
圖4-9 提早終止客戶端鏈接
作到這一點最簡單的方法是在世界各地部署服務器,並複製或緩存您的數據和服務,而不是讓每用戶漂洋過海鏈接到您的主服務器。固然,這也正是許多CDN提供的服務。然而,使用地理上分佈的服務器不能阻止咱們繼續優化。
採用靠近客戶端的服務器來代理創建TLS會話,這意味着TCP和TLS握手往返能夠更快,延遲大大下降。反過來,這個服務器能夠再與主服務器之間創建一個安全的長鏈接,並代理全部傳入的請求和主服務器返回的響應數據。
簡而言之,將服務器移到離客戶更近的地方,加速TCP和TLS握手過程!大多數CDN提供商提供這項服務,若是你喜歡冒險,你也能夠用最少的成本部署本身的基礎設施:利用幾個數據中心的提供的分佈全球的雲服務器,在這些雲服務器上配置代理服務器用來轉發到你服務器的請求,同時添加基於地理的DNS負載均衡,一切OK了。
未緩存源獲取
CDN或代理服務器緩存資源所採用的技術方案,可能須要基於不一樣用戶進行定製,或者因爲一些請求中包含了私有數據致使沒法緩存,所以不可能在CDN中緩存全部的資源,就是俗稱的「未緩存源獲取「。
雖然當數據緩存在基於地理分佈的世界各地服務器中時,CDN的性能達到最優,未緩存起源獲取仍然提供了一個很是重要的優化:客戶端與附近的服務器之間創建TLS鏈接,這仍是能夠顯着減小握手延遲。反過來,CDN或本身的代理服務器,能夠保持一個「活鏈接池」來轉發源服務器的數據,讓你提供一個快速響應給客戶端。
事實上,做爲一種優化技術,一些CDN在通訊的兩端附近都提供了CDN服務器!客戶端與附近的CDN節點創建TLS鏈接,而後這個CDN節點將請求中轉到靠近源服務器的CDN節點,而後請求再被轉發到原服務器。在CDN網絡中增長的這額外一跳容許通訊經由優化的CDN骨幹網絡路由,它能夠進一步下降客戶端和原始服務器之間的延遲。
在靠近用戶的地方創建鏈接,是一種重要的優化手段,這將爲您的用戶在全部的狀況降低低延遲。可是,傳輸再少的數據也快不過什麼都不傳輸。啓用的TLS會話緩存和無狀態恢復,可讓你在重複鏈接時消除一個完整的往返。
TLS會話緩存技術依賴的會話標識符,在SSL 2.0中被引入,目前已經被大多數的客戶端和服務器支持。可是,若是您要配置您的SSL / TLS服務器,不要理所固然的認爲這些在默認狀況下都是支持的。事實上,在默認狀況下,大多數服務器都是關閉的 - 你須要瞭解這一點!你應該仔細檢查並驗證您的配置:
另外,若是客戶端和服務器都支持Session Ticket,則全部的會話數據將被存儲在客戶端上,上述步驟就沒有必要了 - 一切都簡單明瞭了。然而,由於Session Ticket是TLS中一個相對較新的擴展,並不是全部的客戶端都支持。在實際應用中,爲了得到最佳性能,你最好同時啓用兩種方案,對支持Session Ticket的客戶端採用Session Ticket方案,而對舊客戶端採用會話標識做爲備選方案。這些方案都不是排他性的,他們能夠很好的一塊兒工做。
全部經過TLS傳輸的應用數據在都是封裝在記錄協議中( 圖4-8 )。每一個記錄的最大大小是16KB,並根據所選擇的加密算法,每一個記錄將添加20-40字節的額外頭域,MAC,和可選的填充數據。若是記錄隨後被裝入到一個TCP數據包中,那麼咱們還須要添加IP頭和TCP頭:20字節的IP頭,20字節的TCP頭(不帶任何選項)。其結果是,每個記錄都有60〜100字節的潛在開銷。對於一個典型的以太網最大傳輸單元(MTU)大小1500字節,這樣的數據包結構至少有6%的性能損耗。
記錄越小,越高的幀開銷。然而,簡單地將記錄大小設置爲最大尺寸(16 KB)也未必是一個好主意!若是一條記錄跨越多個TCP包,TLS層必須等待全部的TCP報文到達以後,它才能對數據進行解密(
圖4-10 )。若是其中某些TCP報文丟失,從新排序,或因爲擁塞控制而阻塞,那麼TLS記錄的其他片斷都要放在緩衝區中,直到所有收到後才能夠解碼,從而致使額外的延遲。在實際應用中,這些延遲瀏覽器能夠爲瀏覽器帶來了比較嚴重的性能瓶頸,瀏覽器通常傾向於收到一個字節處理一個字節。
圖4-10 Wireshark抓包 11,211字節的TLS記錄分紅了8個TCP Segments
小記錄產生更多冗餘開銷,大記錄產生延遲,沒有一個「徹底準確」的記錄大小。然而,對於Web應用程序來講,主要都是經過瀏覽器進行訪問,最佳作法很簡單:每一個TCP數據包正好包含一個TLS記錄,TLS記錄應該儘可能佔據整個TCP最大段大小(MSS)。換句話說,不要使TLS記錄跨越多個TCP數據包,並在TLS記錄中填充儘量多的數據。基於下面的原則來肯定最佳TLS記錄大小:
假設一個正常的1500字節MTU,這留給TLS記錄的就是在IPv4下大概1420字節,IPv6下1400字節。考慮到將來的需求,最好使用IPv6的大小:若是您的MTU是1400字節,TLS記錄還要少一些。
不幸的是,咱們在應用層很難去控制TLS記錄大小的配置。相反,這一般是TLS服務器的一個設置,設置多是一個編譯器的常量或者標誌 - 如何更新此值的詳細信息,請檢查您的服務器文檔。
若是您的服務器正在處理大量的TLS鏈接,那麼最大限度地減小每一個鏈接內存使用量也是一個重要的優化。默認狀況下,流行的如OpenSSL庫將爲每一個鏈接分配最多50 KB的內存,但根據TLS記錄大小,你能夠檢查文檔或源代碼看看如何調整這個值,這是一個不錯的內存優化點。谷歌的服務器將他們的OpenSSL的緩衝區減小到了約5 KB。
一個不爲人知的TLS特性就是在其紀錄協議中已經內置支持無損數據壓縮:壓縮算法在TLS握手過程當中協商,數據在加密應用以前進行壓縮。然而,在實際應用中,你應該在你的服務器上禁用TLS壓縮,有如下幾個緣由:
重複壓縮會同時在服務器和客戶端浪費CPU時間,另外,安全漏洞的影響也是至關的嚴重 - 所以須要禁用壓縮TLS。在實際應用中,大多數的瀏覽器都是禁用TLS壓縮的,不過,你應該明確的在您的服務器上明確的禁用,以保護您的用戶。
相反,咱們不該該依賴於TLS的壓縮,而是應該在應用層配置Gzip,使全部文本型資源採用gzip方式傳輸,而對其餘格式如圖像,視頻和音頻應該去選取最佳的壓縮格式。
驗證信任鏈要求瀏覽器遍歷證書鏈,從網站證書,並遞歸地驗證證書的父證書,直到達到一個受信任的根證書。所以,首先你應該作的優化就是驗證服務器是否包含了執行握手時的全部中間證書。若是服務器缺失了中間的某個證書,許多瀏覽器將仍然工做,但他們將被迫暫停下來,自行去獲取中間證書、驗證它,而後繼續 - 這可能須要新的DNS查找,TCP鏈接,一個HTTP GET請求,又增長了數百ms的延遲。
瀏覽器如何知道從哪裏獲取中間證書?一般子證書中會包含父證書的地址。
相反,確保你的證書鏈中不要包含沒必要要的證書!或者,更廣泛的是,你應該最大限度地減小您的證書鏈的大小。回想一下,服務器證書在「TLS握手」期間發送 ,這時有可能處於在一個新的TCP鏈接中的前期階段,它正在應用「慢啓動」算法。若是證書鏈超過TCP的初始擁塞窗口(
圖4-11 ),咱們會在不經意間添加了又一往返握手:證書長度超出擁塞窗口大小,並致使服務器中止並等待客戶端的ACK,而後再繼續。
圖4-11 Wireshark抓包 一個5323 byte的TLS證書鏈
圖4-11的證書鏈是超過5 KB,將超過不少舊服務器的初始擁塞窗口大小,並帶來另外一個往返延遲。一個可能的解決方案是增長初始擁塞窗口大小-請參閱「增長TCP的初始擁塞窗口」 。此外,你應該檢查一下是否可能減小證書的大小: