QUICのRFCを説明する(パケット/フレーム概要編)

# 注意
現在記事を工事中です。不自然なつながり、唐突な話題転換等があるかもしれませんのでご了承下さい。

# はじめに
今までにHTTP/1,HTTP/2を実装したことがある(~~というのもおこがましいような出来のものを作ったことがある~~)のだが、
今年6月(追記:この記事を書き始めたのは2022の末でしたがその後2023年まで持ち越して書いています)あたりについに[HTTP/3](https://ja.wikipedia.org/wiki/HTTP/3)がIETFで標準化されたと聞いて、実装してみたくなった。
ところが、HTTP/3はTCPではなくQUIC上で動くというので、まずQUICを実装せねばならない。
よし、実装するぞと早速[RFC9000](https://tex2e.github.io/rfc-translater/html/rfc9000.html)を見始めたのだった...

# 記事を読む前に
この記事(と後々の記事)は基本的に[RFC9000](https://tex2e.github.io/rfc-translater/html/rfc9000.html),[RFC9001](https://tex2e.github.io/rfc-translater/html/rfc9001.html),[RFC9002](https://tex2e.github.io/rfc-translater/html/rfc9001.html)をベースにしています。

QUICの実装はすでに世の中にたくさんあり、

https://github.com/microsoft/msquic

https://github.com/lucas-clemente/quic-go

などの実装や

https://zenn.dev/satoken/articles/golang-quic-protocol

実装方法を解説する記事などもごまんとあるので実装したければそれらを見たほうが早いと思います。

読む前に以下の点(~~言い訳~~)をご了承ください
+ この記事は筆者がRFCについてより理解を深める手助けとして書いているものです。
+ 筆者がQUICのRFCを読む前に読んだことがあったのはHTTP2とHPACKのRFCだけでした。
+ 筆者はRFCを読んで趣味で実装しているだけの素人ですので、不正確な記述があったりする可能性があります。(指摘があれば適宜訂正します)
+ そもそも文章を書くのが下手なので読みづらい可能性があります。
+ 特定のプログラミング言語による実装の詳細については触れません。

(以下文章は常体になります。)

# 最低限の知識
ラウンドトリップやハンドシェイクといった用語や、TLSについての基礎知識、TCPの仕組みになどついては説明しないのでわからない人は別の文献をあたってほしい。また、あらかじめ下記の記事などを読んでQUICの概要について理解しておくと良いだろう。

https://eng-blog.iij.ad.jp/archives/10039

# RFC9000
まずQUICバージョン1の基本となるRFC9000はストリームについての記述に始まり、フロー制御、コネクション、バージョンネゴシエーション、ハンドシェイク、(中略)、実際のバイナリフォーマットの順に(厳密ではないが)上位レイヤーの方から記述されている。

もちろん、実装する上ではストリームの状態遷移とかから実装しても何も問題はないが、RFC初見ではなんの説明もなしにフレームだのPROTOCOL_VIOLATIONだのACK-Elicitingだのという記述が出てきてよくわからないと思う
(筆者はわからなかった。一応see Section xxのような記述があったがそこを見てもsee Section (元の場所)とか書いてあってますます混乱した。~~筆者はバカだったのである~~)。


個人的にはまず最初はバイナリフォーマットの解析と生成の部分を実装してから上位レイヤーを実装していくと良いと思う。


# パケットとフレーム

上に書いた通り筆者はバイナリフォーマットを先に説明したほうが理解しやすいと思うので、まずパケットとフレームについて書く

QUICの通信はパケットの交換によって行われる。
このパケットというのは情報の1単位という意味に過ぎない。
このパケット(以下QUICパケット)はさらにUDPデータグラムに包まれて送信され、そのUDPデータグラムはIPパケットに包まれて送信される。
UDPデータグラムには複数のQUICパケットを含めることができる。
また、IP(プロトコル)にはフラグメンテーションを行う機能があるが、
QUICではこれを禁止している。[^2]

QUICはまた情報の単位としてフレームと言うものを用いる。
これもパケットと同じで情報の1単位という意味に過ぎない。
フレーム(以下QUICフレーム)はパケットのペイロードとして複数のフレームがまとめて送信される。

ここまでの記述を図で表すと以下のようになる
```
┌IP Packet──────────────────────────┐  ┌IP Packet──────────────────────────┐
│ ┌UDP Datagram───────────────────┐ |  │ ┌UDP Datagram───────────────────┐ |
│ │ ┌QUIC Packet─┐ ┌QUIC Packet─┐ │ |  │ │ ┌QUIC Packet────────────────┐ │ |
│ │ │┌QUIC Frame┐│ │┌QUIC Frame┐│ │ |  │ │ │┌QUIC Frame┐  ┌QUIC Frame─┐│ │ |
│ │ │└──────────┘│ │└──────────┘| │ |  | | |└──────────┘  └───────────┘│ │ |
│ │ │            │ │┌QUIC Frame┐| │ |  │ │ │┌QUIC Frame───────────────┐│ │ |
│ │ │            │ │└──────────┘| │ |  | | |└─────────────────────────┘│ │ |
│ │ └────────────┘ └────────────┘ | |  │ │ └───────────────────────────┘ | |
│ └───────────────────────────────┘ |  │ └───────────────────────────────┘ |
└───────────────────────────────────┘  └───────────────────────────────────┘
```

## パケットの種類

QUICパケットにはいくつか種類があり
[RFC9000 17.2. Long Header Packets](https://tex2e.github.io/rfc-translater/html/rfc9000.html#17-2--Long-Header-Packets)の表に[Short Header Packets(1-RTT Packet)](https://tex2e.github.io/rfc-translater/html/rfc9000.html#17-3--Short-Header-Packets)と[VersionNegotiation Packet](https://tex2e.github.io/rfc-translater/html/rfc9000.html#17-2-1--Version-Negotiation-Packet)と[Stateless Reset](https://tex2e.github.io/rfc-translater/html/rfc9000.html#10-3--Stateless-Reset)(厳密にはパケットではない)を加えて以下の種類がある。

```
 +=======+======+=====================+================+
 | Kind  | Type | Name                | Section        |
 +=======+======+=====================+================+
 | Long  | 0x00 | Initial             | Section 17.2.2 |
 +-------+------+---------------------+----------------+
 | Long  | 0x01 | 0-RTT               | Section 17.2.3 |
 +-------+------+---------------------+----------------+
 | Long  | 0x02 | Handshake           | Section 17.2.4 |
 +-------+------+---------------------+----------------+
 | Long  | 0x03 | Retry               | Section 17.2.5 |
 +-------+------+---------------------+----------------+
 | Long  | N/A  | Version Negotiation | Section 17.2.1 |
 +-------+------+---------------------+----------------+
 | Short | N/A  | 1-RTT               | Section 17.3.1 |
 +-------+------+---------------------+----------------+
 | N/A   | N/A  | Stateless Reset     | Section 10.3   |
 +-------+------+---------------------+----------------+
```
これらのうちLong Packetは接続確立(以下ハンドシェイク)時に用いられ、Short Packetはハンドシェイク後に用いられる。

## フレームの種類

また、フレームにもいくつか種類があり、これは[RFC9000 12.4. Frames and Frame Types](https://tex2e.github.io/rfc-translater/html/rfc9000.html#12-4--Frames-and-Frame-Types)に一覧が載っている。
```
+============+======================+===============+======+======+
| Type Value | Frame Type Name      | Definition    | Pkts | Spec |
+============+======================+===============+======+======+
| 0x00       | PADDING              | Section 19.1  | IH01 | NP   |
+------------+----------------------+---------------+------+------+
| 0x01       | PING                 | Section 19.2  | IH01 |      |
+------------+----------------------+---------------+------+------+
| 0x02-0x03  | ACK                  | Section 19.3  | IH_1 | NC   |
+------------+----------------------+---------------+------+------+
| 0x04       | RESET_STREAM         | Section 19.4  | __01 |      |
+------------+----------------------+---------------+------+------+
| 0x05       | STOP_SENDING         | Section 19.5  | __01 |      |
+------------+----------------------+---------------+------+------+
| 0x06       | CRYPTO               | Section 19.6  | IH_1 |      |
+------------+----------------------+---------------+------+------+
| 0x07       | NEW_TOKEN            | Section 19.7  | ___1 |      |
+------------+----------------------+---------------+------+------+
| 0x08-0x0f  | STREAM               | Section 19.8  | __01 | F    |
+------------+----------------------+---------------+------+------+
| 0x10       | MAX_DATA             | Section 19.9  | __01 |      |
+------------+----------------------+---------------+------+------+
| 0x11       | MAX_STREAM_DATA      | Section 19.10 | __01 |      |
+------------+----------------------+---------------+------+------+
| 0x12-0x13  | MAX_STREAMS          | Section 19.11 | __01 |      |
+------------+----------------------+---------------+------+------+
| 0x14       | DATA_BLOCKED         | Section 19.12 | __01 |      |
+------------+----------------------+---------------+------+------+
| 0x15       | STREAM_DATA_BLOCKED  | Section 19.13 | __01 |      |
+------------+----------------------+---------------+------+------+
| 0x16-0x17  | STREAMS_BLOCKED      | Section 19.14 | __01 |      |
+------------+----------------------+---------------+------+------+
| 0x18       | NEW_CONNECTION_ID    | Section 19.15 | __01 | P    |
+------------+----------------------+---------------+------+------+
| 0x19       | RETIRE_CONNECTION_ID | Section 19.16 | __01 |      |
+------------+----------------------+---------------+------+------+
| 0x1a       | PATH_CHALLENGE       | Section 19.17 | __01 | P    |
+------------+----------------------+---------------+------+------+
| 0x1b       | PATH_RESPONSE        | Section 19.18 | ___1 | P    |
+------------+----------------------+---------------+------+------+
| 0x1c-0x1d  | CONNECTION_CLOSE     | Section 19.19 | ih01 | N    |
+------------+----------------------+---------------+------+------+
| 0x1e       | HANDSHAKE_DONE       | Section 19.20 | ___1 |      |
+------------+----------------------+---------------+------+------+
```

また、さらに別のRFCなどで新たな種類のフレームを定義できる。
例えば、[RFC9221](https://tex2e.github.io/rfc-translater/html/rfc9221.html)ではDatagramフレームが定義されている。

# 可変長整数エンコーディング
ここからは実際の具体的なバイナリフォーマットについて説明していく。
まずは、QUICパケットやQUICフレーム、[トランスポートパラメーター](#トランスポートパラメーターとtls)(後述)をパースするのに必要な可変長引数エンコーディングを説明する。

https://ja.wikipedia.org/wiki/%E5%8F%AF%E5%A4%89%E9%95%B7%E6%95%B0%E5%80%A4%E8%A1%A8%E7%8F%BE


以下は[RFC9000 16. Variable-Length Integer Encoding](https://tex2e.github.io/rfc-translater/html/rfc9000.html#16--Variable-Length-Integer-Encoding)に載っている図だ。
```
+======+========+=============+=======================+
| 2MSB | Length | Usable Bits | Range                 |
+======+========+=============+=======================+
| 00   | 1      | 6           | 0-63                  |
+------+--------+-------------+-----------------------+
| 01   | 2      | 14          | 0-16383               |
+------+--------+-------------+-----------------------+
| 10   | 4      | 30          | 0-1073741823          |
+------+--------+-------------+-----------------------+
| 11   | 8      | 62          | 0-4611686018427387903 |
+------+--------+-------------+-----------------------+        
```
QUICの可変長整数の長さは最上位2ビットの値によって決まり、
[ビッグエンディアン](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3%E3%83%87%E3%82%A3%E3%82%A2%E3%83%B3)で格納される。
例えば
```
[0x81,0x3f,0x4b,0x20]
```
のようなバイト列があった場合、最上位2ビットは0x81=0b**10**00,0001なので10となり4バイト整数として最上位2ビット分を削って0x013f4b20=20925216と解釈される。
逆に
```
0x3214
```
という整数値は2byteでエンコードするとしたら、最上位2bitを01にセットすると0x7214=0b**01**11,0010,0001,0100となり
```
[0x72,0x14]
```
という風にエンコードされる。
基本的に実装は各数値を最小の長さになるようにエンコードするとは思うが、必ずしも最小でなくても良い。
ただし、これには例外があってQUICフレームのTypeフィールド(後述)だけは必ず最小の長さでエンコードする必要がある。[^3]

# フレームの基本構造

ここでフレームの基本的な構造について説明する。
個々のフレームの役割については別記事で書くが、どのフレームも以下の構造をもつ。

```
Frame {
    Frame Type (i),
    Type-Dependent Fields (..),
}
```
ここで
```
フィールド名 (i)
```
はフィールドが[可変長整数](#可変長整数エンコーディング)であることを示す。

`Frame Type`というのが、可変長整数のところで述べたQUICフレームのTypeフィールドに当たるところであり、[フレームの種類の表](#フレームの種類)のType Valueの数値がエンコードされる。
`Type-Dependent Fields`は`Frame Type`によって決まるフィールドである。

この設計では、未知の`Frame Type`のフレームを解析することはできないため、新しいフレームを使用したいときは別途[トランスポートパラメーター](#トランスポートパラメーターとtls)などを使用して相手がそのフレームに対応しているか確認する必要がある。

# トランスポートパラメーターとTLS

ここで、トランスポートパラメーターとQUICとTLSの(バイナリフォーマットにおける)関係について簡単に説明する。
トランスポートパラメーターとはQUICのハンドシェイク時に交換され、**相手の**動作を制限(ex:送信可能なデータの上限)したり情報を伝達したり(ex:アイドルタイムアウト(接続の自動切断までの期間))するための手段である。

トランスポートパラメーターは[RFC9000 18. Transport Parameter Encoding](https://tex2e.github.io/rfc-translater/html/rfc9000.html#18--Transport-Parameter-Encoding)に書かれているようにエンコードされる。

```
Transport Parameter {
    Transport Parameter ID (i),
    Transport Parameter Length (i),
    Transport Parameter Value (..),
}
```
`Transport Parameter ID`はID、`Transport Parameter Length`はデータ長、`Transport Parameter Value`が実際のデータである。
[RFC9000 18.2. Transport Parameter Definitions](https://tex2e.github.io/rfc-translater/html/rfc9000.html#18-2--Transport-Parameter-Definitions)などに示されるようにIDごとにデータの意味が決められていて、それに基づいてデータは解釈される。
また、この構造は[フレーム](#フレームの基本構造)とは違ってIDが未知でも全体の長さがわかり、また[新たなフレーム](#フレームの種類)など未対応の要素を無視して接続を続行できるようにするため、未知のIDは無視する必要がある。[^4]

## トランスポートパラメーターとTLSとの関係
このトランスポートパラメーターはどのように運ばれるかというと、[8.2. QUIC Transport Parameters Extension](https://tex2e.github.io/rfc-translater/html/rfc9001.html#8-2--QUIC-Transport-Parameters-Extension)で定義されたquic_transport_parametersというTLS拡張の一種として運ばれる。

ここでTLS拡張について軽く説明しておく。TLS拡張とはHandshakeメッセージ中で様々な拡張情報(鍵交換方式、署名アルゴリズムなど)を伝えるものである。
TLS1.2では必須ではく省略可能だった。
しかしTLS1.3ではTLS1.2でClientHelloの通常のフィールドの一部だったバージョン情報がsupported_version拡張にKey-Exchangeメッセージがkey_share拡張に変更されているため、いくつかの拡張は必須である。

quic_transport_parameters拡張はQUICで通信するときには必須の拡張であり、その中身は`Transport Parameter`を任意の数つなぎ合わせたものである。

また、QUICではquic_transport_parameters拡張の他に[application_layer_protocol_negotiation (ALPN)](https://ja.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation)という拡張も必須で追加しなければならない。[^5]

## TLSとQUICの関係
では、TLSのHandshakeメッセージはどのように運ばれるかというと、[CRYPTOフレーム](#フレームの種類)を用いて運ばれる。
[RFC9000 19.6. CRYPTO Frames](https://tex2e.github.io/rfc-translater/html/rfc9000.html#19-6--CRYPTO-Frames)の図が以下である。
```
CRYPTO Frame {
    Type (i) = 0x06,
    Offset (i),
    Length (i),
    Crypto Data (..),
}
```
`Type`が[フレームの基本構造](#フレームの基本構造)のFrame Typeにあたり、
`Offset`はデータ全体に対するオフセット
`Length`は`Crypto Data`の長さ
`Crypto Data`がTLSのHandshakeメッセージのデータである。

TLSの実装は一連の(分割されていない)Handshakeメッセージを生成し、QUICの実装はそれを適切な長さに分割して送信するという流れである。

また、TLSにはRecordレイヤーがというものがあるが、QUICではそれを使わず、Handshakeメッセージを直に使用する。

[RFC9001 2.1. TLS Overview](https://tex2e.github.io/rfc-translater/html/rfc9001.html#2-1--TLS-Overview)の図と[RFC9001 3. Protocol Overview](https://tex2e.github.io/rfc-translater/html/rfc9001.html#3--Protocol-Overview)の図を比較してみる。
Figure 1: TLS Layers
```
             +-------------+------------+--------------+---------+
   Content   |             |            |  Application |         |
   Layer     |  Handshake  |   Alerts   |     Data     |   ...   |
             |             |            |              |         |
             +-------------+------------+--------------+---------+
   Record    |                                                   |
   Layer     |                      Records                      |
             |                                                   |
             +---------------------------------------------------+
```
Figure 3: QUIC Layers
```
   +--------------+--------------+ +-------------+
   |     TLS      |     TLS      | |    QUIC     |
   |  Handshake   |    Alerts    | | Applications|
   |              |              | |  (h3, etc.) |
   +--------------+--------------+-+-------------+
   |                                             |
   |                QUIC Transport               |
   |   (streams, reliability, congestion, etc.)  |
   |                                             |
   +---------------------------------------------+
   |                                             |
   |            QUIC Packet Protection           |
   |                                             |
   +---------------------------------------------+
```

TLS LayersのHandshakeのメッセージがQUIC LayersのTLS Handshake(CRYPTO Frame)として送信される。

#  Initialパケットの構造

ここで少し話を変えて、

まず、最初に使うのはInitial Packetだ。
[RFC9000 17.2.2. Initial Packet](https://tex2e.github.io/rfc-translater/html/rfc9000.html#17-2-2--Initial-Packet)から図を引用する。
```
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..),
}
```
ここで軽く見方を説明すると、
```
フィールド名 (ビット数)
```
と言う形式が基本で、
```
フィールド名 (i)
```
という表記が先程説明した、可変長整数という意味、
```
フィールド名 (0..160)
```
というのは`0ビットから160ビットの間の長さ`。
`(0..160)`などは実際にはバイト単位でしか長さを変えられないので`0バイトから20バイトの間の長さ`と捉えれば良い。
```
フィールド名 (..)
```
は任意長。

上記２つの形式には長さを示すフィールドが前についている場合が多い。例えばInitial Packetの場合だと`Token Length`が`Token`の長さとなっている。

また、
```
フィールド名 (1) = 1
```
など `= 1`などとあるのは`そのフィールドの値は1で固定`という意味である。

さて、話を戻そう。
InitialPacketの構造は以下のようになっている。
```
Header Form (1) = 1
```
まず、これはロングヘッダパケットかショートヘッダパケットかを示すフラグである。
`Header Form`が`1`のときはロングヘッダパケットであると決められてるので[^3]、InitialPacketはロングヘッダパケットとわかる。これは他のパケットでも同様である。
```
Fixed Bit (1) = 1
```
これは固定ビットだ。とりあえず`1`に設定しておけば良い。[^5]
```
Long Packet Type (2) = 0
```
これは他の種類のロングヘッダパケットと区別するためのビットだ。
ロングヘッダパケットは全部で4種類なので2bitあれば十分なのである。
[RFC9000 17.2. Long Header Packets](https://tex2e.github.io/rfc-translater/html/rfc9000.html#17-2--Long-Header-Packets)から図を引用する
QUICバージョン1では以下のように対応している[^4]
```
+======+===========+================+
| Type | Name      | Section        |
+======+===========+================+
| 0x00 | Initial   | Section 17.2.2 |
+------+-----------+----------------+
| 0x01 | 0-RTT     | Section 17.2.3 |
+------+-----------+----------------+
| 0x02 | Handshake | Section 17.2.4 |
+------+-----------+----------------+
| 0x03 | Retry     | Section 17.2.5 |
+------+-----------+----------------+
           
```
他のパケットについてはおいおい説明していこう。
```
Reserved Bits (2)
```
これは予約ビットだ。このビットは将来のために予約されているがバージョン1では`00`で埋めておかなければならない。
ちなみにロングヘッダパケットではこのフィールドと次の`Packet Number Length`フィールドは「ヘッダー保護」の対象になっている。これは後ほど説明しよう。
```
Packet Number Length (2)
```
これは`Packet Number`フィールドの長さである。
パケット番号というのは各パケットごとにつけられる番号で、これでパケットが到達したかを調べるのに使われる。(TCPのシーケンス番号に似た役割である)

ちなみにここまででQUICのヘッダはまだ1バイト分である。
QUICはTCPのようにヘッダにいろいろ詰め込むのではなく、パケットとフレームで役割を分担しているのである。[^6]

```
Version (32)
```
これはQUICのバージョンを表す4バイトの整数である。バージョン1は0x00000001で表す。[^7]
```
Destination Connection ID Length (8)
Destination Connection ID (0..160)
```
これは宛先コネクションIDの長さとIDそのものである。
コネクションIDというのはQUIC上で接続を識別するものである。
QUICはUDP上で動作するのだがこれによって同じIPアドレスやポートでもからの接続を多重化することができる。
また逆に、UDPのIPアドレスとポート以外にコネクションIDを設けることでIPアドレスとポートが変わってもコネクションIDを使って異なるIPアドレスとポートでも同じ接続として扱えるのである。
詳しいことは別の記事で説明する。
```
Source Connection ID Length (8)
Source Connection ID (0..160)
```
これは送信元コネクションIDの長さとIDそのものである。
```
Token Length (i)
Token (..)
```
これは0RTT用のトークンの長さとトークンの値である。
今回は使用しないので割愛する。
```
Length (i)
```
これは、`Length`フィールド以降のパケットの長さである。
InitialパケットとZeroRTTパケットとHandshakeパケットにはこのフィールドが存在し、これによって1つのUDPデータグラムに複数のQUICパケットを入れるということが可能になる。
なお、これを計算するときにはいくつか注意があるのがそれは次回の記事で説明する。
```
Packet Number (8..32)
```
これは、パケット番号である。先ほど説明したのでそちらを参照していただきたい。なお、このパケット番号の長さは1,2,3,4バイトのいずれかであり、`Packet Number Length`フィールドの値に1を足すことで求められる。なお、ちなみにこの部分もヘッダー保護の対象であり、暗号化される。

なぜ`Packet Number Length`と`Packet Number`が暗号化されるかというと、これらのフィールドを暗号化することでこれを復号しない限りパケット番号がわからないようにすることができるのである。
これは[TCPシーケンス番号予測攻撃](https://ja.wikipedia.org/wiki/TCP%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E7%95%AA%E5%8F%B7%E4%BA%88%E6%B8%AC%E6%94%BB%E6%92%83)のように第三者がパケット番号を予測して接続を乗っ取るということができなくなるということにつながる。

```
Packet Payload (8..)
```
これは、パケットのペイロードである。
この中身にフレームを並べたものが入る。
[Rfc9000 12.4. Frames and Frame Types](https://tex2e.github.io/rfc-translater/html/rfc9000.html#12-4--Frames-and-Frame-Types)から図を引用する。
```
Packet Payload {
  Frame (8..) ...,
}
```
このようなイメージである。`(8..)`とあるのは最低1バイトはなければならないという意味である。ただし、実際には暗号化の都合によって20バイト以上なければならないのだがこれは次回述べる。

# 次回予告

さて、ここまでで
+ フレームとパケットの基本
+ フレームとパケットの種類一覧
+ 可変長整数
+ フレームの構造
+ トランスポートパラメーターについて
+ TLSとQUICの関係の概要
+ CRYPTOフレームの役割

については説明した。
[次回](https://qiita.com/on-keyday/items/6011a1f87d254ac124b7)はTLSとQUICの関係の詳細を説明する。


[^2]: https://tex2e.github.io/rfc-translater/html/rfc9000.html#14--Datagram-Size の記述 "UDP datagrams MUST NOT be fragmented at the IP layer."

[^3]: https://tex2e.github.io/rfc-translater/html/rfc9000.html#16--Variable-Length-Integer-Encoding の記述 "Values do not need to be encoded on the minimum number of bytes necessary, with the sole exception of the Frame Type field"

[^4]: https://tex2e.github.io/rfc-translater/html/rfc9000.html#7-4-2--New-Transport-Parameters の記述 "An endpoint MUST ignore transport parameters that it does not support."

[^5]: https://tex2e.github.io/rfc-translater/html/rfc9001.html#8-1--Protocol-Negotiation の記述 "Unless another mechanism is used for agreeing on an application protocol, endpoints MUST use ALPN for this purpose."

[^6]: [RFC9000 17.2. Long Header Packets](https://tex2e.github.io/rfc-translater/html/rfc9000.html#17-2--Long-Header-Packets)参照
[^7]: バージョン1ではとわざわざ書いたのは、バージョン2では違うマッピングになる予定であるからである。QUIC バージョン2で検索してみてほしい。
[^8]: greasing quic bitという仕様があり、特定のトランスポートパラメータ(別記事)があるとランダム化が可能になる。[RFC9287](https://tex2e.github.io/rfc-translater/html/rfc9287.html)を参照されたし。
[^9]: 例えばTCPではACK番号がヘッダに含まれているが、QUICではACK Frameで送信するようになっている
[^10]: じゃあバージョン2は0x00000002かというとそうではない。QUICバージョン2で検索してほしい。