簡介
自從HTTP從1.1升級到了2,一切都變得不同了。雖然HTTP2沒有強制說必須使用加密協議進行傳輸,但是業界的標準包括各大流行的瀏覽器都只支援HTTPS情況下的HTTP2協議。
那麼怎麼在HTTPS之中加入HTTP2協議的支援呢?今天本文將會跟大家聊一下SSL/TLS協議的擴充套件NPN和ALPN。
SSL/TLS協議
SSL(Secure Socket Layer)安全套接層,是1994年由Netscape公司設計的一套協議,並與1995年釋出了3.0版本。
TLS(Transport Layer Security)傳輸層安全是IETF在SSL3.0基礎上設計的協議,實際上相當於SSL的後續版本。
SSL/TLS是一種密碼通訊框架,他是世界上使用最廣泛的密碼通訊方法。
TLS主要分為兩層,底層的是TLS記錄協議,主要負責使用對稱密碼對訊息進行加密。
上層的是TLS握手協議,主要分為握手協議,密碼規格變更協議和應用資料協議4個部分。
其中最重要的就是握手協議,通過客戶端和伺服器端的互動,和共享一些必要資訊,從而生成共享金鑰和互動證書。
接下來我們一步步的介紹每一步的含義:
-
client hello
客戶端向伺服器端傳送一個client hello的訊息,包含下面內容:
- 可用版本號
- 當前時間
- 客戶端隨機數
- 會話ID
- 可用的密碼套件清單
- 可用的壓縮方式清單
我們之前提到了TLS其實是一套加密框架,其中的有些元件其實是可以替換的,這裡可用版本號,可用的密碼套件清單,可用的壓縮方式清單就是向伺服器詢問對方支援哪些服務。
客戶端隨機數是一個由客戶端生成的隨機數,用來生成對稱金鑰。
-
server hello
伺服器端收到client hello訊息後,會向客戶端返回一個server hello訊息,包含如下內容:
- 使用的版本號
- 當前時間
- 伺服器隨機數
- 會話ID
- 使用的密碼套件
- 使用的壓縮方式
使用的版本號,使用的密碼套件,使用的壓縮方式是對步驟1的回答。
伺服器隨機數是一個由伺服器端生成的隨機數,用來生成對稱金鑰。
-
可選步驟:certificate
伺服器端傳送自己的證書清單,因為證書可能是層級結構的,所以處理伺服器自己的證書之外,還需要傳送為伺服器簽名的證書。
客戶端將會對伺服器端的證書進行驗證。如果是以匿名的方式通訊則不需要證書。 -
可選步驟:ServerKeyExchange
如果第三步的證書資訊不足,則可以傳送ServerKeyExchange用來構建加密通道。
ServerKeyExchange的內容可能包含兩種形式:
- 如果選擇的是RSA協議,那麼傳遞的就是RSA構建公鑰密碼的引數(E,N)。我們回想一下RSA中構建公鑰的公式:\(密文=明文^E\ mod\ N\), 只要知道了E和N,那麼就知道了RSA的公鑰,這裡傳遞的就是E,N兩個數字。具體內容可以參考RSA演算法詳解
- 如果選擇的是Diff-Hellman金鑰交換協議,那麼傳遞的就是金鑰交換的引數,具體內容可以參考更加安全的金鑰生成方法Diffie-Hellman
-
可選步驟:CertificateRequest
如果是在一個受限訪問的環境,比如fabric中,伺服器端也需要向客戶端索要證書。
如果並不需要客戶端認證,則不需要此步驟。 -
server hello done
伺服器端傳送server hello done的訊息告訴客戶端自己的訊息結束了。 -
可選步驟:Certificate
對步驟5的回應,客戶端傳送客戶端證書給伺服器
-
ClientKeyExchange
還是分兩種情況:
- 如果是公鑰或者RSA模式情況下,客戶端將根據客戶端生成的隨機數和伺服器端生成的隨機數,生成預備主密碼,通過該公鑰進行加密,返送給伺服器端。
- 如果使用的是Diff-Hellman金鑰交換協議,則客戶端會傳送自己這一方要生成Diff-Hellman金鑰而需要公開的值。具體內容可以參考更加安全的金鑰生成方法Diffie-Hellman,這樣伺服器端可以根據這個公開值計算出預備主密碼。
-
可選步驟:CertificateVerify
客戶端向伺服器端證明自己是客戶端證書的持有者。
-
ChangeCipherSpec(準備切換密碼)
ChangeCipherSpec是密碼規格變更協議的訊息,表示後面的訊息將會以前面協商過的金鑰進行加密。
-
finished(握手協議結束)
客戶端告訴伺服器端握手協議結束了。
-
ChangeCipherSpec(準備切換密碼)
伺服器端告訴客戶端自己要切換密碼了。
-
finished(握手協議結束)
伺服器端告訴客戶端,握手協議結束了。
-
切換到應用資料協議
這之後伺服器和客戶端就是以加密的方式進行溝通了。
NPN和ALPN
上面我們介紹SSL/TLS協議的時候,最後一步是切換到應用資料協議,那麼客戶端是怎麼和伺服器端討論協商具體使用哪種應用資料協議呢?是使用HTTP1.1?還是HTTP2?還是SPDY呢?
這裡就要用到TLS擴充套件協議了。而NPN(Next Protocol Negotiation) 和 ALPN (Application Layer Protocol Negotiation) 就是兩個TLS的擴充套件協議。
他們主要用在TLS中,用來協商客戶端和伺服器端到底應該使用什麼應用資料協議進行溝通。
其中NPN是SPDY使用的擴充套件,而ALPN是HTTP2使用的擴充套件。
他們兩個有什麼區別呢?
相較於NPN來說,ALPN在client hello訊息中已經列出了客戶端支援的應用層協議,伺服器端只需要從中選擇出它支援的協議即可。比NPN少了一個互動的步驟,所以ALPN是推薦的協議。
下面是具體的互動流程圖:
互動的例子
下面以ALPN為例,講解下具體的互動流程,首先是客戶端傳送”Client Hello“訊息:
Handshake Type: Client Hello (1)
Length: 141
Version: TLS 1.2 (0x0303)
Random: dd67b5943e5efd0740519f38071008b59efbd68ab3114587...
Session ID Length: 0
Cipher Suites Length: 10
Cipher Suites (5 suites)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 90
[other extensions omitted]
Extension: application_layer_protocol_negotiation (len=14)
Type: application_layer_protocol_negotiation (16)
Length: 14
ALPN Extension Length: 12
ALPN Protocol
ALPN string length: 2
ALPN Next Protocol: h2
ALPN string length: 8
ALPN Next Protocol: http/1.1
可以看到在client hello訊息中的Extension欄位中,使用了ALPN,並且列出了可以選擇使用的兩種ALPN Protocol:h2和http/1.1。
對應的“server hello” 訊息會選擇出具體使用的ALPN protocol如下:
Handshake Type: Server Hello (2)
Length: 94
Version: TLS 1.2 (0x0303)
Random: 44e447964d7e8a7d3b404c4748423f02345241dcc9c7e332...
Session ID Length: 32
Session ID: 7667476d1d698d0a90caa1d9a449be814b89a0b52f470e2d...
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Compression Method: null (0)
Extensions Length: 22
[other extensions omitted]
Extension: application_layer_protocol_negotiation (len=5)
Type: application_layer_protocol_negotiation (16)
Length: 5
ALPN Extension Length: 3
ALPN Protocol
ALPN string length: 2
ALPN Next Protocol: h2
如上所示,伺服器端選擇了h2, 最終當客戶端和伺服器端TLS握手結束之後,會選擇使用HTTP2作為後續的應用層資料協議。
總結
NPN和ALPN都是TLS的擴充套件,相較而言,ALPN更加好用。
本文已收錄於 http://www.flydean.com/08-ssl-tls-npn-alpn/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!