フラグメンテーション
IPパケットが、次に送る回線のMTUより大きいときに、複数の小さなパケット(フラグメント)に分割して送ること。分割されたパケットは、宛先のホストで元に組み立て直される。
イマシルちゃんの解説
大きな荷物が、トンネルの入口より大きくて通れないとき、
荷物をいくつかの箱に分けて、それぞれに「全部で何個のうち何個目か」を書いて送るよね。
IPのフラグメンテーションは、これと同じなんだ。
バラバラになった箱は、最後に宛先でまとめて元に戻すんだよ。
ただ、1箱でもなくなったら全部やり直しになっちゃうから、なるべく分けずに済むようにするのが大事なんだ!
より深い解説
定義
フラグメンテーション(フラグメント化)は、IPv4で、パケットの大きさが送出するインタフェースのMTUを超える場合に、データ部を分割して、それぞれにIPヘッダーを付けた複数のパケット(フラグメント)にする処理である。途中のルータは組み立て直さず、最終的な宛先のホストだけが再組み立てを行う。
分割に使うIPv4ヘッダーのフィールド
| フィールド | 役割 |
|---|---|
| 識別子(Identification) | 元が同じパケットのフラグメントに、同じ値を付ける |
| DFビット(Don't Fragment) | 1のとき、分割を禁止する。MTUを超えたら、ルータはパケットを捨てて、ICMPで送信元に知らせる |
| MFビット(More Fragments) | 1のとき、後ろにまだフラグメントが続く。最後のフラグメントは0 |
| フラグメントオフセット | このフラグメントのデータが、元のデータのどの位置にあたるかを、8オクテット単位で示す |
分割の計算例
IPヘッダー20オクテット、データ3,000オクテットのパケットを、MTU 1,500の回線に送る場合
- 1つのフラグメントに入るデータ:1,500 − 20 = 1,480オクテット(8の倍数)
| フラグメント | データ長 | オフセット | MF |
|---|---|---|---|
| 1つ目 | 1,480 | 0 | 1 |
| 2つ目 | 1,480 | 1,480 ÷ 8 = 185 | 1 |
| 3つ目 | 40 | 2,960 ÷ 8 = 370 | 0 |
最後のフラグメント以外のデータ長は、オフセットを8オクテット単位で表すため、8の倍数にする。
分割の問題点
| 問題 | 内容 |
|---|---|
| 効率の低下 | フラグメントごとにIPヘッダーが付き、ルータや受信側の処理の負荷が増える |
| 損失への弱さ | フラグメントが1つでも失われると、元のパケット全体が使えなくなる(TCPなら全体を再送する) |
| セキュリティ | 2つ目以降のフラグメントにはTCPやUDPのヘッダーがないため、ファイアウォールで検査しにくい。重なり合うフラグメントで検査をすり抜ける攻撃もある |
そのため、TCPでは、MSSやパスMTU探索によって、最初から分割の不要な大きさで送るのが一般的である。
IPv6のフラグメント
IPv6では、途中のルータは分割しない。MTUを超えるパケットを受け取ったルータは、パケットを捨てて、ICMPv6のPacket Too Bigを送信元に返す。分割が必要な場合は、送信元が、フラグメントヘッダー(拡張ヘッダーの1つ)を使って分割する。
TCPのデータ長の求め方
「フラグメント化されることなく送れるTCPのデータの最大長」は、MTUからIPヘッダーとTCPヘッダーを引いたMSSである。MTUが1,500オクテットなら、1,500 − 20 − 20 = 1,460オクテットになる。