QUIC協議詳解

LightningStar發表於2022-03-07

宣告

本文可以自由轉載但需註明原始連結。本文為本人原創,作者LightningStar,原文發表在部落格園。本文主體內容參考論文[1]完成。

介紹

QUIC,發音同quick,是"Quick UDP Internet Connections"的簡稱,是一種通用的傳輸層網路協議。QUIC與TCP相同,是一種有連線的傳輸協議。但是與TCP不同的是QUIC是建立在UDP傳輸層協議之上的,實現了在兩個端點之間的多路複用。QUIC的是在使用者空間實現的,TCP/UDP則是在核心空間實現的。[2]

QUIC所處的網路層次如下圖所示。圖源文獻[1:1]

image_204

優勢

Quic 相比現在廣泛應用的 http2+tcp+tls 協議有如下優勢:
1、減少了 TCP 三次握手及 TLS 握手時間。
2、改進的擁塞控制。
3、避免隊頭阻塞的多路複用。
4、連線遷移。
5、前向安全。

建立連線(握手)

QUIC實現了快速握手,並把握手過程分為兩種情況,分別是1-RTT和0-RTT。在介紹這兩種握手過程之前,讀者需自行熟悉Diffie-Hellman演算法的基本原理[3]

image_202

在上圖(文獻[1:2])中顯示了三種不同情況的連線過程。其中最左邊的圖表示的是第一次連線時的情況,中間的圖表示重複連線的情況(在一定條件下,客戶端可以重新連線伺服器而不需要從初始化情況連線),最右邊的圖則是重連失敗之後從初始話連線的情況。最後一種情況是第一種情況的組會,0-RTT也是1-RTT的一部分,後文中將重點介紹1-RTT的連線過程。

1-RTT

QUIC_1_RTT

第一次握手

  • 客戶端主動向伺服器傳送Inchoate CHLO報文
  • 伺服器會向客戶端傳送REJ報文。REJ報文包含了伺服器的配置資訊,如長期的Diffie-Hellman值,伺服器配置的簽名,source-address-token(stk, 用於驗證的加密塊,包含有伺服器看到的客戶端的IP地址和伺服器當前的時間戳,之後客戶端會將該stk發回)等,為了進行身份證明還會使用私鑰進行簽名,同時也可以防篡改;
  • 在收到伺服器的配置資訊後,客戶端會通過證書鏈機制驗籤,並實現對伺服器的身份認證。

第二次握手

  • 客戶端在通過對伺服器的驗證之後,客戶端會生成一個Diffie-Hellman值。此時客戶端有了自身和對方的Diffie-Hellman值,就可以計算出初始金鑰(initial key, ik);
  • 客戶端將包含有DH公開之的明文Complete CHLO傳送至伺服器;
  • 客戶端使用ik對請求資料加密,傳送至伺服器;
  • 伺服器收到Complete CHLO之後就可以獲得客戶端的Diffie-Hellman的值,就可以計算出初始金鑰。
  • 伺服器立即向客戶端傳送SHLO報文(ik加密的)。SHLO報文含有一個伺服器臨時Diffie-Hellman值,可以用於計算前向安全的金鑰(會話金鑰);
  • 伺服器收到加密的請求資料,使用初始金鑰進行解密;
  • 伺服器使用會話金鑰對響應資料進行加密,發回給客戶端。
  • 客戶端在收到SHLO之後使用初始金鑰解密得到伺服器的臨時DH公開值,根據該臨時值計算出會話金鑰;
  • 客戶端收到加密的響應資料後,使用會話金鑰進行解密。

整個握手過程會在2個RTT內完成。

0-RTT

客戶端在重連同一個伺服器時,會使用已經快取的伺服器相關配置資訊(stk,DH公開值等資訊),並直接向伺服器傳送Complete CHLO報文,並使用ik對請求報文進行加密。但是伺服器方面會標識相應的stk等資訊已經過期,這時伺服器會傳送REJ資訊,客戶端需要重新與伺服器進行連線。

如果沒有過期的話,就可以直接建立連線,省下了重新建立連線的開銷。

前向安全性

所謂前向安全性就是指,在最後一次握手時,會生成一個會話金鑰sk。這樣即使伺服器的長期DH值被破獲,且生成了初始金鑰ik,也無法對會話中的資料進行解密。

多路複用機制

基於TCP的應用程式會在TCP單位元組流抽象層中實現多路複用。為了避免由於TCP順序傳遞導致的頭部阻塞(head-of-line blocking)[4],QUIC支援在單個UDP連線中複用多個流,並保證UDP報文的丟失僅影響相應的流,而不會影響其他的流(stream)。

可以在QUIC流上構建任意大小的應用程式報文,最多支援\(2^{64}\)的位元組。並且stream的實現是輕量級的,即使訊息報文很小也可以為它們使用單獨的流。每一個Stream都有stream ID唯一標識。這些流ID由客戶端/伺服器進行靜態分配。客戶端主動發起的流的ID永遠是奇數,伺服器發起的流的ID是偶數。這樣可以避免衝突。當在一個未使用過的流上傳送資料時,流會自動建立;當需要關閉時,就會在最後一幀資料上設定一個FIN的標誌指示接收方關閉流。如果傳送方或接收方確定不再需要流上的資料,則可以取消流,而無需斷開整個 QUIC 連線。儘管流是可靠的抽象,但 QUIC 不會為已取消的流重新傳輸資料。

一個QUIC包是由一個公共的頭後面跟著一個或多個幀組成的,如下圖(圖源[1:3])所示。QUIC流複用是通過將流資料封裝在一個或多個流幀中來實現的,單個QUIC包可以攜帶來自多個流的流幀.

image_205

報文丟失重傳

TCP 序列號有助於提高可靠性,並表示在接收方傳送位元組的順序。這種混淆會導致“重傳模糊”(retransmission ambiguity)問題,因為重傳的 TCP 段攜帶與原始資料包相同的序列號 。 TCP ACK 的接收者無法確定 ACK 是為原始傳輸還是為重傳而傳送,並且通常通過昂貴的超時來檢測重傳段的丟失。每個 QUIC 資料包都攜帶一個新的資料包編號,包括那些攜帶重傳資料的資料包。這種設計不需要單獨的機制來區分重傳的 ACK 和原始傳輸的 ACK,從而避免了 TCP 的重傳模糊問題。流幀中的流偏移用於傳遞排序,資料包編號表示一個明確的時間順序,這使得丟失檢測比 TCP 更簡單、更準確。

QUIC的ACK顯示地記錄了接收的資料包文和ACK之間的延遲。單調增加的報文編號一起,可以精確估算RTT,有助於丟失檢測。QUIC的確認報文支援多達256個ACK,這是使得QUIC比帶有SACK的TCP更能適應重新排序或丟失的情況下線上路上保留更多位元組。

更多內容參見[5]

流量控制(Flow Control)

當應用程式從QUIC的接收緩衝區中讀取資料較慢時,留戀控制就會限制接收者必須保持的接收緩衝區大小。一個緩慢耗盡的stream會逐漸耗盡整個連線connection的緩衝區,因此必須要限制QUIC連線上的每個流可以消耗的緩衝區大小,避免消耗其他流的緩衝區的大小。這樣可以改善流之間潛在的隊頭阻塞(head-of-line blocking)。因此QUIC採用連線級別的流量控制(connection-level flow control),這樣可以限制傳送者在所有流中接收者使用的聚合緩衝區;採用流級別的流量控制(stream-level flow control)可以限制傳送者在任何給定流上使用的緩衝區。

與HTTP/2類似,QUIC採用基於信用的流量控制。QUIC接收器在每個流中通告接收器願意接收資料的絕對位元組偏移量。在特定流上傳送、接收和傳遞資料時,接收器會定期傳送視窗更新幀,以增加該流的視窗偏移限制,從而允許對等方在該流上傳送更多資料。連線級流量控制的工作方式與流級流量控制相同,但傳遞的位元組數和接收到的最高偏移量是所有流的。

擁塞控制(Congestion Control)

QUIC支援的擁塞控制演算法有:
Reno(TCP用的)、基於Pacing的擁塞控制演算法(PBCCA)、TCP CUBIC等。

連線遷移

QUIC連線使用隨機生成的64bit的cid唯一確定。cid允許客戶機在網路之間漫遊,而不受網路或傳輸層引數變化的影響。

cid使得客戶端能夠獨立於網路地址轉換(network address translation, NAT)之外。cid 在路由中起著重要作用,特別是用於連線標識的目的。此外,使用 cids 可以通過探測連線的新路徑實現多路徑。

在連線遷移期間,端點假設對等方願意在其當前地址接受資料包。因此,端點可以遷移到新的 IP 地址,而無需首先驗證對等方的 IP 地址。新的路由路徑可能不支援端點的當前傳送速率。在這種情況下,端點需要重新構建它的擁塞控制器。另一方面,從一個新的對等地址接收非探測包 ,確認對等地址已遷移到新的 IP 地址。

實現參考

  • Google Quic Project[6]

擴充閱讀

參考文獻


  1. LANGLEY A, RIDDOCH A, WILK A, 等. The QUIC Transport Protocol: Design and Internet-Scale Deployment[C/OL]//Proceedings of the Conference of the ACM Special Interest Group on Data Communication. Los Angeles CA USA: ACM, 2017: 183-196[2022-03-05]. https://dl.acm.org/doi/10.1145/3098822.3098842. DOI:10.1145/3098822.3098842. ↩︎ ↩︎ ↩︎ ↩︎

  2. QUIC wikipedia ↩︎

  3. 應用密碼學 | Diffie-Hellman金鑰交換演算法 ↩︎

  4. 關於隊頭阻塞(Head-of-Line blocking),看這一篇就足夠了 ↩︎

  5. J. Iyengar and I. Swett. 2016. QUIC Loss Detection and Congestion Control.IETF Internet Draft, draft-ietf-quic-recovery ↩︎

  6. QUIC Crypto ↩︎

  7. KUMAR P, DEZFOULI B. Implementation and analysis of QUIC for MQTT[J/OL]. Computer Networks, 2019, 150: 28-45. DOI:10.1016/j.comnet.2018.12.012. ↩︎

相關文章