上篇主要是介紹了HTTP存在的兩大安全問題web
從而引出了TLS。本篇就來着重介紹下TLS。算法
提及TLS可能有些人還比較陌生,但若是說到SSL,那知道的人就更多了。TLS其實就是SSL發展而來,版本演進大致爲SSL 2.0 -> SSL 3.0 -> TLS 1.0(能夠看作是SSL 3.1版)。chrome
TLS主要提供三個基本服務瀏覽器
其中第三點是網絡協議中經常使用的一個校驗和機制,和咱們這邊要說的安全話題不是太相關,再也不贅述。而前兩點正好是對應了HTTP的兩個問題,下面分別介紹下。緩存
其實網絡通訊能夠類比爲人之間的對話,好比A和B之間須要溝通,但兩人無法直接見面,但有一個傳話人能夠代爲傳話。這樣兩人就能間接溝通了,只不過這個傳話的過程是有必定風險(被記錄,被篡改)的。安全
對話明文服務器
爲了不這種風險,長此以往A和B想出了一個辦法:他們約定使用傳話人不會的上海話溝通。這樣每次傳話人都聽不懂啥意思,只能儘量有樣學樣地把A說給他的話學給B聽。cookie
對話加密網絡
這個普通話翻譯成上海話的過程,對於傳話人來講就是一種內容的『加密』。但這個方法不必定是惟一的,可能之後另外一個傳話人懂上海話呢?因而在每次使用方言溝通以前,A和B會先行溝通下他們此次對話使用的語種(兩人真是牛逼!)session
協商機制
這個選擇語種的過程,其實就是兩人之間關於翻譯方式的『協商』過程。傳話人要想從中搗鬼,就能立馬被發現,這樣AB兩人爲了溝通安全就會中止此次溝通,轉而找其餘的傳話人傳話了。
協商失敗
以上看到AB兩人機智的採用『翻譯』『協商』兩招完成的安全溝通了。將一樣的方法拿到網絡通訊中,就是TLS的加密機制了。
TLS握手
這個圖描述了發送端和接收端是怎麼協商他們之間的加密機制的。TLS協議是基於TCP協議之上的,圖中第一個藍色往返是TCP的握手過程,不在本文範疇中按下不表。以後的兩次橙色的往返,就是咱們要重點說的協商過程了,能夠叫作TLS的握手。握手過程以下:
咱們一步一步來仔細看。
第一步,客戶說明他支持的全部加密套件(就像上海話、廣東話同樣)讓服務端選擇一個。這裏和Server1還完成了一個TLS選項的協商,這能夠理解爲在肯定核心的加密方式的同時,順便溝通下是否能支持一些『附加功能』。這些附加功能先按下不表,後續會介紹兩個經常使用的。
第二步,服務端選擇了加密套件。加密算法都是須要一個祕鑰的,服務端這裏給出的是本身的公鑰。這裏的公鑰其實蘊含着一個關鍵點:祕鑰協商過程採用了不對稱加密。簡單來講,通常的對稱加密以下
encrypt(明文,祕鑰) = 密文
decrypt(密文,祕鑰) = 明文
也就是說加密和解密用的是一個祕鑰。而非對稱加密就比較神奇了
encrypt(明文,公鑰) = 密文
decrypt(密文,私鑰) = 明文
加密和解密是須要不一樣的密鑰的。在TLS握手前,客戶端自己不知道服務器的祕鑰的,若是運用對稱加密,那麼服務端告訴客戶端祕鑰的過程當中,二者之間的中間節點其實也拿到祕鑰了,這樣後續二者之間的加密通訊,對於中間節點來講也能解密出內容了。所以這裏採用不對稱加密,服務端給出一個公鑰供客戶端後續使用。此外這一步服務端還提供了證書,而且可能要求客戶端提供證書。關於證書下文會提到,只要有了證書,就能保證和你通訊的對方是真實的,而不是別人僞造的。這裏只要先理解,客戶端看到服務端證書後,就可以相信服務端並使用服務端給的公鑰了。
第三步,客戶端給出了雙方後續加密通訊所要使用的對稱密鑰,經過服務器公鑰加密後返回給服務端。因爲對稱密鑰是被不對稱加密算法加密起來的,所以中間節點拿到後,沒有辦法解密出真正的內容。
第四步,服務端拿公鑰對應的私鑰解密出真正的對稱密鑰,至此加密算法和加密所需的密鑰都肯定,服務端給客戶端發送一個finish完成握手,證實雙方都已經準備好加密通訊了。以後雙方的交互均可以使用對稱加密算法加密了。
說完了如何肯定加密的算法和密鑰後,咱們再說說那所謂的『附加功能』。所謂TLS的擴展,就是在TLS協議核心保持不變的基礎上,對其進行擴展以使其支持更多的特性,這裏簡單介紹下兩個擴展:ALPN和SNI。
ALPN(Application Layer Protocol Negotiation)即應用層協議協商,旨在將原來應用層協議中的協議協商,提早合併到TLS握手時完成,減小一次往返時間。這裏經過一個例子來講明下什麼叫作應用層的協議協商。假設TLS握手完成了,接下來客戶端和服務端就應該開始進行正常的HTTP通訊了,可是客戶端認爲HTTP協議比較慢(還記得上篇提到的流式傳輸的效率問題嗎),在請求內容以前先向服務端提出『咱們能不能換HTTP2.0通訊』。服務端會根據本身支持HTTP2.0的狀況給出答覆,以後客戶端會根據服務端的答覆,使用HTTP或HTTP2.0向服務端請求內容。能夠看到這個過程當中又多了一次協商升級協議的往返,致使客戶端拿到返回結果的延遲更大了。爲了優化這一點,在HTTP使用TLS加密的時候,會使用ALPN擴展,把協商升級協議的請求放在Client1中,服務端在Server1就返回說是否能夠升級協議。這樣TLS握手以後,客戶端就能夠直接按HTTP2.0發起請求而沒必要多一次往返了。
SNI(Server Name Indication)叫作服務器名稱指示,主要是支持服務端同一個機器部署有多個站點的狀況的。前面說的證書、公鑰私鑰,都是針對某個站點來講的。網站A和網站B可能租了同一臺服務器,但他們的證書和密鑰必定是不一樣的。當客戶端請求到這臺公用服務器時,服務器也不知道該返回哪一個站點的信息了。這個時候使用SNI擴展,在client1帶上訪問站點的信息,服務端看到後,就會去找對應站點的證書、密鑰了。
任何事物都是有利有弊,引入TLS機制當然是可以保證安全,但卻在TCP握手和HTTP通訊之間,多加了兩個往返的TLS握手過程。特別是現代網頁應用中充滿了AJAX請求的場景下,請求的每每都是一個很小的資源,在一波TCP包中就能返回的。這種狀況下握手須要三次往返,而真正有意義的請求往返只有一次,安全的代價很是大!(關於延遲對於性能的重要性,怎麼強調都不爲過,但每每會被人所忽視。這裏不展開,但能夠仔細思考下TCP的擁塞避免策略:在大延遲的狀況下TCP包須要等上一波TCP包的往返後纔會繼續發送。這就是爲何不少人都是50兆100兆的寬帶還常常以爲上網慢的緣由,由於延遲大!而運營商是歷來不會宣傳或保證延遲這個指標的)
固然,仍是有優化的辦法的。上篇說過,現代web應用常常是打開一個網頁同時會發送幾十個請求。TLS握手這個協商加密套件和密鑰的過程,須要重複幾十次嗎?固然不用。既然這幾十個請求都是請求的同一個網站,那共用第一次請求的協商結果就行了。這樣雖然第一次請求中TLS握手的代價很大(好比佔了50%),但從整個網頁全局看來,代價就下降到了百分之幾了。目前一些主流瀏覽器的實現也確實利用了這個機制:他們會刻意先發起一個請求,待該請求的TLS連接完成後,再併發發起其餘的請求。後續併發的請求就可以利用TLS協商後的結果了。
這種對協商結果的複用叫作TLS的『會話恢復機制』,主要有兩種方案:Session Identifier 和 Session Ticket。
Session Identifier即會話標識符,是一種服務端保存會話信息的方案。
方案總體思路其實和web應用的session相似,都是在服務端維護信息,客戶端提供一個sessionId。所以該方案面臨和session同樣的挑戰:服務端須要管理海量會話信息而且制定適當的淘汰策略。
Session Ticket即會話記錄單,是一種客戶端保存會話信息的方案。
這個方案的總體思路就和cookie相似了,有效地減輕了服務端的壓力。但這屬於一種較新的機制,目前還不是全部客戶端都支持。
上面這麼大篇幅都是介紹的TLS如何完成『加密』這個事情,然而以前說到的HTTP另外一個問題『沒法驗證服務器的真實性』仍是沒有獲得解決。畢竟若是有個節點要假裝成服務器,和用戶進行TLS的加解密交互,也是徹底沒問題的吧。所以,TLS中還須要經過『證書機制』來保證你所訪問的服務器是真實的。從安全層面來講,『證書』和『加密』是同等重要的兩個機制。
作個假設,你和小A是朋友,大家之間什麼事均可以暢所欲言。大家當面聊天時,你不介意把本身的隱私和小A分享。你的分享,實際上是創建在『當面』的基礎上的,也就是你經過『辨識小A的外貌』來判定他的真實性後,纔會信任他與他分享。若是有一天小A經過一個陌生的電話聯繫你,那你恐怕就不會這麼毫無防備了。爲了驗證電話那頭真的是小A,大家之間可能須要一些驗證機制,好比讓小A說說大家小時候發生的某個事或者在大家兩個面對面的時候肯定個暗號。這個事件或者暗號,其實就是你用來認證小A的『證書』了。 這樣你和小A之間的認證就OK了。可有一天,一個自稱小A朋友的小B找到你,想叫你幫個忙,能夠你以前歷來沒據說太小B。這個時候爲了驗證小B是不是可信的,你只能找來小A幫忙了。你聯繫小A使用大家之間的『證書』驗證其真實性後,由小A使用他和小B約定的『證書』來驗證小B的真實性。驗證成功後,你也就能信任小B了吧,畢竟你的朋友小A已經信任電話那頭的小B了。
這個找小A驗證小B的過程,正是TLS中核心的『證書鏈』機制。
證書鏈
前面說到,在TLS握手過程當中服務端會提供給客戶端它的證書。這個證書可不是隨意生成的,而是經過指定的權威機構申請頒發的。服務端若是可以提供一個合法的證書,說明這個服務端是合法的,能夠被信任。就拿上圖來講
整個過程包含兩個關鍵點
先說說第一個問題,權威的根證書頒發機構很是少,所以瀏覽器和操做系統都會內置一些可信的根證書頒發機構,也就是說這些機構的權威性是由瀏覽器或操做系統保證的。但曾經也出現過一些並不權威的證書因爲某些目的被內置在中國版的Firefox中這樣的事件,讓人直呼防不勝防。
CNNIC
好在當前大多數狀況下跟證書仍是可以保證權威的,若是是CNNIC這種系統性風險,那也只有靠多關注安全新聞來及時避免了。經過系統或瀏覽器配置就能查看到本身內置可信的跟證書頒發機構了,這裏是我mac的結果。若是發生了像上述CNNIC證書的問題,只要到證書列表這裏刪除對應的可信證書便可。
mac自帶跟證書
再來講說第二個問題,如何從證書頒發者那裏驗證某個證書的有效性。每一個證書頒發機構在頒發證書的同時,有義務維護其認證站點的權威性:好比每一個證書都有過時時間,一旦到期就要當即失效;某個站點須要更換證書服務商,換上新的證書時,老的也就當即要失效,不然老的證書可能會被挪用到不法站點上;因爲站點自身問題致使私鑰泄密,那麼TLS的加密就不能保證安全;證書頒發機構被冒名頂替等等。一旦發生以上任何一種狀況,證書頒發者都要保證對應證書當即失效。證書頒發者通常提供兩種方式來驗證證書有效性:CRL和OCSP。
CRL(Certificate Revocation List)即證書撤銷名單。證書頒發者會提供一份已失效證書的名單,供瀏覽器驗證證書使用。固然這份名單是巨長無比的,瀏覽器不可能每次TLS都去下載,因此經常使用作法是瀏覽器會緩存這份名單,按期作後臺更新。這樣雖而後臺更新存在時間間隔,證書失效不實時,但通常也OK了。
OCSP(Online Certificate StatusProtocol)即在線證書狀態協議。除了離線文件,證書頒發者也會提供實時的查詢接口,查詢某個特定證書目前是否有效。實時查詢的問題在於瀏覽器須要等待這個查詢結束才能繼續TLS握手,延遲會很大。此外,經過『某個IP請求了某個證書的OCSP請求』這個信息,其實就暴露了某個用戶正在訪問某個網站了,也算是一種隱私的泄露。
以上是站在證書頒發者的角度說明會提供兩種判斷方式,實際狀況下瀏覽器究竟會選擇哪一種方式判斷,每一個瀏覽器都有本身的實現。下圖是經過chrome查看某個網站的證書信息,能夠看到其中的證書鏈和證書驗證信息。
證書例子
介紹完證書如何保證站點的可信之後,咱們來看看若是證書不合法會怎麼樣。致使不合法證書還能被使用有兩種狀況,一種是前文提到的CNNIC證書等相似的系統性風險,另外一種是用戶缺少安全意識,手動信任了存在安全隱患的證書。
惡意節點被信任
對於前者,咱們要多關注安全新聞按期排雷,對於後者咱們要提升安全意識,之後看到這些畫面時可要慎之又慎了,而不是一味地點贊成。
ie
chrome
firefox
一旦非法的證書被瀏覽器視爲合法,那麼就面臨着一種『中間人攻擊』的風險:惡意節點會經過持有的非法證書和客戶端交互,以後代替客戶端,向真實服務器發起請求,並把服務器的請求返回給客戶端。這樣客戶端好像感受本身直接鏈接了服務器,但實際上有個隱藏的中間人,神不知鬼不覺地竊取了中間的信息。
中間人攻擊
至此,已經將TLS技術如何應對『明文』和『沒法驗證服務器的真實性』兩個主要安全問題講完了,因爲本人並不從事網工相關職業,所以就沒有深究到協議消息幀細節,只是從原理層面進行了理解。若是關於TLS還有什麼沒有提到,或者理解不正確的,歡迎各位提出來~
做者:jimsshom 連接:https://www.jianshu.com/p/24af67c40e8d 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。