在經過昨天的反思後,今後討論的方向還是會先著重在協定交互的行為,至於封包觀察可以等後續如果在寫程式做實驗的時候,方便拿來觀察程式的運作有沒有符合預期。
今天要探討的主題是 QUIC 中很重要的 Connection ID,他是如何決定的,雙方協商的過程又是如何進行。
QUIC connection 可以想成 Client 端與 Server 端共享狀態的一種抽象概念。
一個 connection 始於 Client 與 Server 開始 Handshake 的時候,雙方在 Handshake 的過程會交換金鑰用於後續的加密傳輸,除此之外,在建立連線的過程中也會交換一些可選的 transport parameters。
雙方協商 connection ID 時也會使用到 transport parameters,在稍後的介紹會看到。
底下的示意圖可以參考一下,說明為什麼 connection 會是抽象結構
可以看到在前幾天討論的封包格式外,幾個欄位之前組合起來也代表著抽象的意義,像是 Header 的 Connection ID 等其實實際意義就代表的 Connection 的存在,這種抽象的概念要實作會比較方便,可以定義出 Connection, Stream 等 class,方便管理。
在昨天的文章有提到,Packet 有分成 Long Header Packet, Short Header Packet,在雙方協商的時候使用 Long Header Packet 的另一個原因就是需要把要協商的 Connection ID 擺在 Header 的欄位中。
Long Header Packet 中與 Connection ID 的欄位有
Destination Connection ID Length
Destonation Connection ID
Source Connection ID Length
Source Connection ID
一開始 Client 端會生成自己的 Connection ID 放在 Source Connection ID
欄位,這時候因為還沒有跟 Server 溝通過,所以 Destination Connection ID 還不清楚,隨機生成一個放到 Initial Packet 的 Destination Connection ID
欄位。
隨機生成的 Destination Connection ID 長度至少要 8 bytes,在還沒有跟 Server 端取得連線之前都必須要使用這個隨機生成的 DCID 填入 Destination Connection ID
欄位。
這個隨機生成的 DCID 其實是有用的,不僅僅只是因為還沒有獲得 Server 的 Connection ID 而已,在 Initial Packet 也使用這個 DCID 進行所謂的 packet protection,這個在後面的章節會介紹到,簡單來說就是 QUIC 除了 Payload 的加密外,對於 Packet 的 Header 也會進行一定的保護。
Client 傳送的 Source Connection ID 對 Server 來說必須要填入 Destination Connection ID,這應該滿直觀的,但一開始名詞很多的情況下有時候會混淆整個流程,一開始 Client 傳送 SCID 給 Server,Server 接受後傳填入回傳封包的 Destination Connection ID
欄位,並且把 Server 端生成的 Connection ID 填入 Source Connection ID
欄位。
當 Client 首次收到 Server Initial 或者 Retry packet,就必須要把封包的 Destination Connection ID
欄位改成 Server 傳過來的 Source Connection ID
。(對於 Client 來說,Server 的 Source 代表 Client 的 Destination)
自此 Server 往後的 Destination Connection ID
也必須要使用從 Client Initial packet 傳來的 Connection ID,除非收到 NEW_CONNECTION_ID frame,如果後續又收到 Client 傳來的 Initial packet 包含不同的 Source Connection ID
則必須要直接丟棄。
如果對交換 Connection ID 過程感興趣的讀者,可以根據前幾天介紹 wireshark 的流程觀察,會發現 Client 的確一開始會生成一個隨機的 DCID,之後收到 Server 的回應後就會把 DCID 改成 Server 的 SCID。
今天主要介紹了一開始建立連線時雙方交換 Connection ID 的過程,明後天我們會來探討如何認證 Connection ID,因為在 Long Header Packet 中的 ID 欄位都是以明碼傳輸,QUIC 利用 transport parameter 來驗證雙方的 Connection ID 有沒有在過程中被人更改,那麼明天見!