Wiresharkパケット解析メモ

Wiresharkでパケット解析

QUICプロトコルの解析 - Initialシーケンス

前回の続き。

QUICの1-RTT Handshakeシーケンス

QUICの初期セッションの確立においては、1-RTT Handshakeシーケンスを用いる。 Initial及びRetryシーケンス、Handshakeシーケンスから構成される。

f:id:packet_analysis:20210808230519p:plain
QUICの1-RTT Handshakeシーケンス

今回はInitialシーケンスについて。

Initialシーケンス

InitialシーケンスではServer - Client間でConnection IDの設定を実施する。 (同時に実施されるClient Hello/Server HelloからHandshakeシーケンスについては次回)

Initial(Client → Server 1回目)

ClientからServerに対してDestination Connection ID (サーバを識別するコネクションID) を通知する。

ClientがServerからInitialパケット or Retryパケットを受信していない場合、Clientは8Bytes以上のランダム値をDestination Connection IDフィールドに設定する(MUST)。 [RFC 9000 7.2]

続くペイロードにはTLS 1.3のClient Helloを含める。

以下の例だとa39456398973fb79が該当。

QUIC IETF
    1... .... = Header Form: Long Header (1)
    .1.. .... = Fixed Bit: True
    ..00 .... = Packet Type: Initial (0)
    .... 00.. = Reserved: 0
    .... ..00 = Packet Number Length: 1 bytes (0)
    Version: draft-29 (0xff00001d)
    Destination Connection ID Length: 8
    Destination Connection ID: a39456398973fb79
    Source Connection ID Length: 0
    Token Length: 0
    Length: 1332
    Packet Number: 3

Retry (Server → Client)

Serverは、Server側のコネクションを識別するためのDestination Connection IDを任意に設定し、RetryパケットのSource Connection IDフィールドに設定してClientに送信する。

続くInitialを識別するためのRetry Tokenと、Retryパケットの正当性確認のためのRetry Integrity Tag [RFC 9001 5.8] も付与する。

以下の例だと459be263f78e84e90f99f4e66af27b2690e9c583がコネクションID。

QUIC IETF
    1... .... = Header Form: Long Header (1)
    ..11 .... = Packet Type: Retry (3)
    Version: draft-29 (0xff00001d)
    Destination Connection ID Length: 0
    Source Connection ID Length: 20
    Source Connection ID: 459be263f78e84e90f99f4e66af27b2690e9c583
    Retry Token: 576af22978557f29143112e3ec2af60b9834b7abf3390281592b107978d6aaaa622e4927…
    Retry Integrity Tag: 6149bd84c4c658e28937f499268ef74f 

Initial(Client → Server 2回目)

Retryパケットの受信後、ClientはRetryパケットに含まれるSource Connection IDでDestination Connection IDを更新する。[RFC 9000 7.2]

また、Retryパケット受信を契機としたConnection ID変更であることの正当性担保のため、Retryパケットに含まれるRetry TokenをTokenフィールドに設定して送信する。[RFC 9000 17.2.5.2]

続くペイロードに含めるTLS 1.3のClient Helloは、1回目のInitialと同じものを設定する。

QUIC IETF
    QUIC Connection information
    [Packet Length: 1350]
    1... .... = Header Form: Long Header (1)
    .1.. .... = Fixed Bit: True
    ..00 .... = Packet Type: Initial (0)
    .... 00.. = Reserved: 0
    .... ..00 = Packet Number Length: 1 bytes (0)
    Version: draft-29 (0xff00001d)
    Destination Connection ID Length: 20
    Destination Connection ID: 459be263f78e84e90f99f4e66af27b2690e9c583
    Source Connection ID Length: 0
    Token Length: 64
    Token: 576af22978557f29143112e3ec2af60b9834b7abf3390281592b107978d6aaaa622e4927…
    Length: 1255
    Packet Number: 4

Initial (Server → Client)

Clientからの2回目のInitialが問題ない場合、ServerはInitialパケットで応答する。 ServerはClientを識別するためのSource Connection IDを設定する。

続くペイロードにはTLS 1.3のServer Hello/ACKを含めて送信する。さらに、Initialパケットに続けてHandshakeパケットを同一UDPデータグラムに設定する。

QUIC IETF
    1... .... = Header Form: Long Header (1)
    .1.. .... = Fixed Bit: True
    ..00 .... = Packet Type: Initial (0)
    .... 00.. = Reserved: 0
    .... ..00 = Packet Number Length: 1 bytes (0)
    Version: draft-29 (0xff00001d)
    Destination Connection ID Length: 0
    Source Connection ID Length: 20
    Source Connection ID: bdfa6963f4b15db20457c3262371f4c85764ba7d
    Token Length: 0
    Length: 116
    Packet Number: 0
    Payload: 1afd2a2ef815351a8cf07bb40341aafad55a798b09a1eff9e5c8ea77135b6b49bd90091c…
    TLSv1.3 Record Layer: Handshake Protocol: Server Hello
    ACK
QUIC IETF
    1... .... = Header Form: Long Header (1)
    .1.. .... = Fixed Bit: True
    ..10 .... = Packet Type: Handshake (2)
    .... 00.. = Reserved: 0
    .... ..00 = Packet Number Length: 1 bytes (0)
    Version: draft-29 (0xff00001d)
    Destination Connection ID Length: 0
    Source Connection ID Length: 20
    Source Connection ID: bdfa6963f4b15db20457c3262371f4c85764ba7d
    Length: 1071
    Packet Number: 0
    Payload: 077be1a4fe43c6564ef3f20bba747a1cbf3e3b65209252d2c8414b6bb151694589df8b8a…
    TLSv1.3 Record Layer: Handshake Protocol: Multiple Handshake Messages

パケットフォーマット

Initialパケット

RFC 9000 17.2.2章で以下のように定義されている。

   Initial Packet {
     Header Form (1) = 1,
     Fixed Bit (1) = 1,
     Long Packet Type (2) = 0,
     Reserved Bits (2),
     Packet Number Length (2),
     Version (32),
     Destination Connection ID Length (8),
     Destination Connection ID (0..160),
     Source Connection ID Length (8),
     Source Connection ID (0..160),
     Token Length (i),
     Token (..),
     Length (i),
     Packet Number (8..32),
     Packet Payload (8..),
   }

Header Form (1bit)

  • Long Header Packetでは1、Short Header Packetでは0を設定する。
  • Initial PacketはLong Header Packetのみなので "1" 固定。

Fixed Bit (1bit)

  • Version Negotiation Packet以外では1を設定する。
  • Initial Packetでは "1" 固定。

Long Packet Type (2bits)

  • Initial Packetでは "00" を設定する。
  • 他のパケットタイプの設定値は以下の通り
    • 0-RTT Packet : 01
    • Handshake Packet : 02
    • Retry Packet : 03

Reserved Bit (2bits)

  • "00"を設定する。

Packet Number Length (2bits)

  • Packet Numberフィールド長(Bytes) - 1を設定する (e.g., 1 Bytesなら0を設定)

Version (32bits)

  • 準拠するQUICのバージョンを設定する。
  • draft-29の場合、0xff00001dを設定。
    • 上位2バイト : draftの場合、ffに設定
    • 下位6バイト : バージョンを設定 (29 = 0x1d)

Destination Connection ID Length (8bits)

  • Destination Connection ID長(Bytes)を設定する。
  • 最大20Bytesなので最大値は20。

Destination Connection ID (0~160bits)

  • Server側でコネクションを識別するためのDestination Connection IDを設定する。
  • Initial送信時以降、ServerからのRetry受信時、ServerからのInitial受信時の2回更新される。

Source Connection ID Length (8bits)

  • Source Connection ID長(Bytes)を設定する。
  • 最大20Bytesなので最大値は20。

Source Connection ID (0~160bits)

  • Client側でコネクションを識別するためのSource Connection IDを設定する。

Token Length (8bits)

  • 次に続くToken長(Bytes)を設定する。
  • Tokenが存在しない場合は"0"を設定する。
  • ServerはInitialにTokenを設定しない。

Token (~256Bytes)

  • Client verificationのため、RetryパケットでRetry Tokenが指定された場合にはRetry Tokenと同値を入れてInitialを再送する。

Packet Length (1~8Bytes)

  • Packet Lengthより後のパケット長を示す。
    • = Packet NumberフィールドとPacket Payloadフィールド長の合計。
  • 最上位2ビットの値によってPacket Lengthに使用するビット長が変化する (Section 16)。
  • 最上位2ビットが"01"の時、Packet Lengthは14bits (0-16383)となる。
    • e.g., 0x4534 = 0100 0101 0011 0100 → 上位2ビットが"01"のため、続く14ビットがPacket Length。
    • 続く14ビットは00 0101 0011 0100 = 0x534 = 1332なのでPacket Length = 1332Bytes。

Packet Number (1~4Bytes)

  • Packet Number Lengthフィールドで指定された長さのフィールドで、パケット番号を設定する。

Retryパケット

RFC 9000 17.2.5章で以下のように定義されている。

   Retry Packet {
     Header Form (1) = 1,
     Fixed Bit (1) = 1,
     Long Packet Type (2) = 3,
     Unused (4),
     Version (32),
     Destination Connection ID Length (8),
     Destination Connection ID (0..160),
     Source Connection ID Length (8),
     Source Connection ID (0..160),
     Retry Token (..),
     Retry Integrity Tag (128),
   }

Header Form (1bit)

  • Long Header Packetでは1、Short Header Packetでは0を設定する。
  • Retry PacketはLong Header Packetのみなので "1" 固定。

Fixed Bit (1bit)

  • Version Negotiation Packet以外では1を設定する。
  • Retry Packetでは "1" 固定。

Long Packet Type (2bits)

  • Retry Packetでは "0x03" を設定する。
  • 他のパケットタイプの設定値は以下の通り
    • 0-RTT Packet : 0x01
    • Handshake Packet : 0x02
    • Retry Packet : 0x03

Version (32bits)

  • 準拠するQUICのバージョンを設定する。
  • draft-29の場合、0xff00001dを設定。
    • 上位2バイト : draftの場合、ffに設定
    • 下位6バイト : バージョンを設定 (29 = 0x1d)

Destination Connection ID Length (8bits)

  • Destination Connection ID長(Bytes)を設定する。
    • Retry PacketではDestination Connection IDは設定しないので0を設定。
  • 最大20Bytesなので最大値は20。

Destination Connection ID (0~160bits)

  • Server側でコネクションを識別するためのDestination Connection IDを設定する。
    • Retry PacketではDestination Connection IDは設定しない。

Source Connection ID Length (8bits)

  • Source Connection ID長(Bytes)を設定する。
  • 最大20Bytesなので最大値は20。

Source Connection ID (0~160bits)

  • Client側で2回目のInitialで設定すべきServer側のDestination Connection IDを設定する。
  • ClientはRetry Packetで受信したSource Connection IDを次回のInitial packetのDestination Connection IDに設定する。

Token Length (8bits)

  • 次に続くToken長(Bytes)を設定する。
  • Retry Packetでは設定必須。

Token (~256Bytes)

  • Server側でRetryに伴うInitialを識別するため、Initial再送時にClientに設定してもらうRetry Tokenを指定する。

Retry Integrity Tag (128bits)

  • RFC 9001 5.8で規定される、Retryパケットの完全性確認 (Integrity) のためのタグ
  • AEAD_AES_128_GCMの認証付き暗号 (AEAD: Authenticated Encryption with Associated Data) を利用して認証と完全性の確認を行う

長くなってきたので、Handshakeシーケンスに続きます…

詳解HTTP/2 (Programmer's SELECTION)