フラグメント化されたパケットとは、1つの大きなIPパケットが、ネットワーク上を通過できるサイズに合わせて複数の小さな断片に分割されたものです。
日本語では「断片化されたパケット」「IPフラグメント」などとも呼ばれます。
ネットワークには、1回で送信できるデータサイズの上限があります。
この上限を MTU といいます。
MTU は Maximum Transmission Unit の略で、最大転送単位を意味します。
たとえば、一般的なEthernet環境では、IP MTUが 1500バイト であることが多いです。
ただし、Jumbo Frame、PPPoE、VPN、トンネル、クラウドネットワーク、コンテナネットワークなどでは、MTUが1500バイトより大きくなったり、小さくなったりする場合があります。
大きなIPパケットが経路上のMTUを超えると、そのままでは通過できません。
そのため、送信元や途中の機器によってパケットが分割されることがあります。これがフラグメント化です。
ネットワークごとに、1回で運べるパケットサイズには上限があります。
たとえば、ある経路にMTU 1500バイトの区間がある場合、1500バイトを超えるIPパケットはそのまま通過できません。
元のIPパケット: 4000バイト
↓ MTU 1500バイトの経路を通過する必要がある
Fragment 1: 1500バイト以下
Fragment 2: 1500バイト以下
Fragment 3: 残り
このように、大きなIPパケットを複数の小さなIPフラグメントに分割することで、MTUの小さいネットワークでも転送できるようにします。
フラグメント化は、基本的には IP層 の処理です。
TCPやUDPなどのトランスポート層よりも下の、ネットワーク層で扱われます。
アプリケーション層
トランスポート層 TCP / UDP
ネットワーク層 IP ← フラグメント化が関係する層
データリンク層 Ethernet / Wi-Fi など
物理層
アプリケーション側から見ると単にデータを送っているように見えても、IP層では複数のフラグメントに分割されていることがあります。
IPv4では、送信元ホストだけでなく、途中のルーターでもフラグメント化が発生することがあります。
ただし、後述する DFフラグ が設定されている場合、ルーターはそのパケットをフラグメント化しません。
その場合、MTUを超えているパケットは破棄され、送信元へICMPエラーが返されます。
IPv4ヘッダーには、フラグメント化と再構成のために重要なフィールドがあります。
| フィールド | 役割 |
|---|---|
| Identification | どの元パケットに属するフラグメントかを識別する |
| Flags | 分割禁止や、後続フラグメントの有無を示す |
| Fragment Offset | 元のIPパケット内で、この断片がどの位置にあったかを示す |
受信側はこれらの情報を使って、複数のフラグメントを元のIPパケットに戻します。
Identification は、複数のフラグメントが同じ元パケットから分割されたものであることを示すための識別番号です。
たとえば、1つのIPパケットが3つに分割された場合、その3つのフラグメントは同じIdentification値を持ちます。
元パケットA
├─ Fragment A-1
├─ Fragment A-2
└─ Fragment A-3
すべて同じIdentification値を持つ
受信側はIdentificationを見て、「これらは同じ元パケットの断片である」と判断します。
IPv4ヘッダーのFlagsでは、主に次の2つが重要です。
| フラグ | 意味 |
|---|---|
| DF | Don’t Fragment。分割禁止 |
| MF | More Fragments。後続フラグメントあり |
DF は Don’t Fragment の略です。
DFフラグが立っているパケットは、途中のルーターによってフラグメント化されません。
そのため、パケットサイズが経路上のMTUを超えている場合、ルーターはそのパケットを破棄します。
そして、送信元に対して「フラグメント化が必要だがDFが設定されている」という内容のICMPエラーを返します。
この仕組みは、Path MTU Discovery で重要になります。
MF は More Fragments の略です。
MFフラグは、「この後にもフラグメントが続く」ことを示します。
たとえば、1つのIPパケットが3つに分割された場合、通常は次のようになります。
Fragment 1: MF = 1
Fragment 2: MF = 1
Fragment 3: MF = 0
最後のフラグメントだけ、MFが0になります。
Fragment Offset は、そのフラグメントが元のIPパケットのどの位置にあったかを示す値です。
受信側はFragment Offsetを見て、各フラグメントを正しい順番に並べ直します。
IPv4のFragment Offsetは、8バイト単位 で表されます。
たとえば、最初のフラグメントがIPペイロードを1480バイト持っていた場合、次のフラグメントのOffsetは次のようになります。
1480 ÷ 8 = 185
つまり、
Fragment 1: Offset = 0
Fragment 2: Offset = 185
となります。
この仕様のため、最後以外のフラグメントでは、IPペイロードのサイズが8バイトの倍数になるように調整されます。
IPv4パケットのデータ部分が4000バイトあり、経路上のMTUが1500バイトだとします。
IPv4ヘッダーが20バイトの場合、1つのフラグメントで運べるIPペイロードの最大サイズは次のようになります。
MTU 1500バイト - IPv4ヘッダー 20バイト = 1480バイト
4000バイトのデータを1480バイトずつ分割すると、次のようになります。
| フラグメント | データサイズ | Offset | MF |
|---|---|---|---|
| Fragment 1 | 1480バイト | 0 | 1 |
| Fragment 2 | 1480バイト | 185 | 1 |
| Fragment 3 | 1040バイト | 370 | 0 |
Offsetの計算は次の通りです。
Fragment 2のOffset: 1480 ÷ 8 = 185
Fragment 3のOffset: 2960 ÷ 8 = 370
この例では、最初の2つのフラグメントには後続があるためMFが1になります。
最後のフラグメントには後続がないため、MFは0になります。
IPv4では、途中のルーターがパケットをフラグメント化することがあります。
しかし、分割されたフラグメントを元のIPパケットに戻す処理は、基本的に最終的な受信先ホストで行われます。
送信元
↓
途中のルーターでフラグメント化
↓
複数のIPフラグメントとして配送
↓
受信先ホストで再構成
途中のルーターがフラグメントを元に戻すわけではありません。
フラグメント化されたパケットは、すべての断片が揃って初めて元のIPパケットに戻せます。
1つでもフラグメントが失われると、元のIPパケット全体を再構成できません。
Fragment 1: 到着
Fragment 2: 消失
Fragment 3: 到着
→ 元のIPパケットを復元できない
このため、フラグメント化はパケットロスに弱いという問題があります。
IPv6では、IPv4とは考え方が異なります。
IPv6では、途中のルーターはパケットをフラグメント化しません。
必要な場合は、送信元ホストがFragment Headerを使ってフラグメント化します。
| 項目 | IPv4 | IPv6 |
|---|---|---|
| 途中ルーターによるフラグメント化 | あり得る | しない |
| フラグメント化する主体 | 送信元またはルーター | 送信元のみ |
| 再構成する主体 | 受信先ホスト | 受信先ホスト |
| MTU超過時の扱い | DFなしなら分割され得る | ルーターはPacket Too Bigを返す |
IPv6では、最小MTUとして 1280バイト が重要です。
IPv6の各リンクは、少なくとも1280バイトのIPv6パケットを配送できることが前提とされています。
そのため、IPv6では送信元が経路上のMTUを考慮し、必要に応じて送信サイズを調整します。
IPv6でパケットが大きすぎて通過できない場合、ルーターはそのパケットを破棄し、送信元へ ICMPv6 Packet Too Big メッセージを返します。
送信元はこのメッセージをもとに、より小さいサイズでパケットを送るように調整します。
Path MTU Discovery は、通信経路全体で通過できる最大パケットサイズを調べる仕組みです。
通信経路には、複数のネットワークが含まれることがあります。
送信元
↓ MTU 1500
ルーターA
↓ MTU 1400
ルーターB
↓ MTU 1280
受信先
この場合、経路全体で安全に通過できる最大サイズは1280バイトです。
Path MTU Discoveryを使うことで、送信元は経路上の最小MTUに合わせてパケットサイズを調整できます。
IPv4では、DFフラグを立てたパケットを送信します。
途中のルーターでMTUを超える場合、そのルーターはパケットを破棄し、送信元へICMPエラーを返します。
送信元はその情報をもとに、より小さいパケットサイズで再送します。
IPv6では途中ルーターがフラグメント化しないため、Path MTU Discoveryの重要性がより高くなります。
パケットが大きすぎる場合、ルーターはICMPv6 Packet Too Bigを送信元へ返します。
送信元はそれを受け取り、送信サイズを下げます。
Path MTU Discoveryには、PMTUDブラックホール と呼ばれる問題があります。
これは、途中のファイアウォールやルーターがICMPエラーを遮断してしまうことで発生します。
1. 送信元が大きなパケットを送る
2. 経路上のMTUを超える
3. ルーターがICMPエラーを返そうとする
4. 途中でICMPが遮断される
5. 送信元はMTUを下げるべきことに気づけない
6. 通信が止まる、または極端に遅くなる
PMTUDブラックホールが発生すると、次のような症状が出ることがあります。
| 症状 | 内容 |
|---|---|
| Webサイトの一部だけ表示されない | HTMLは読めるが画像やJSが止まる |
| VPN経由で一部サービスだけ遅い | カプセル化により実効MTUが下がる |
| SSHはつながるが大きな転送が止まる | 小さい通信は通るが大きい通信で失敗する |
| 特定のサイトだけ開けない | 経路上のMTUやICMP遮断が影響する |
ICMPをすべて遮断すると、セキュリティ上安全に見える場合があります。
しかし、PMTUDに必要なICMPまで遮断すると、通信障害の原因になります。
TCPでは、MSS という値を使って、1つのTCPセグメントで送るデータサイズを調整します。
MSS は Maximum Segment Size の略です。
たとえば、IPv4 + TCPで、MTUが1500バイト、IPヘッダーとTCPヘッダーにオプションがない場合、MSSは次のようになります。
MTU 1500
- IPv4ヘッダー 20
- TCPヘッダー 20
= MSS 1460
この場合、TCPデータを1460バイト以内に収めることで、IPパケット全体を1500バイト以内にできます。
TCPデータ 1460バイト
+ TCPヘッダー 20バイト
+ IPv4ヘッダー 20バイト
= 1500バイト
そのため、TCP通信では通常、IPフラグメント化が起きにくいように調整されます。
IPv6では、IPv6基本ヘッダーが40バイトです。
MTU 1500バイト、TCPヘッダー20バイト、オプションなしの場合、MSSは次のようになります。
MTU 1500
- IPv6ヘッダー 40
- TCPヘッダー 20
= MSS 1440
そのため、IPv4とIPv6では同じMTU 1500でも、一般的なMSSの値が異なります。
TCPヘッダーにオプションが付く場合や、VPN・PPPoE・トンネルなどで追加ヘッダーが付く場合、実際に使えるデータサイズはさらに小さくなります。
そのため、実務ではMSSを適切に調整することが重要です。
MSS clamping は、ルーターやファイアウォールがTCPのMSS値を小さく書き換える仕組みです。
VPNやPPPoEなどでは、追加ヘッダーの影響で実効MTUが下がることがあります。
その状態でMSSが大きいままだと、IPフラグメント化やMTU超過による通信障害が起きやすくなります。
そこで、TCP SYNパケット内のMSSオプションを小さく調整します。
元のMSS: 1460
↓
調整後MSS: 1360
これにより、TCPは最初から小さめのセグメントを使うようになり、フラグメント化を避けやすくなります。
MSS clampingは、特に次のような環境で有効です。
| 環境 | 理由 |
|---|---|
| VPN | カプセル化でヘッダーが増える |
| PPPoE | Ethernetより実効MTUが小さくなる |
| IPsec | 暗号化・認証ヘッダーが追加される |
| GREトンネル | トンネルヘッダーが追加される |
| クラウド間接続 | 経路やトンネル構成によりMTUが変わる |
UDPには、TCPのようなMSS交渉や再送制御がありません。
そのため、大きなUDPデータグラムを送ると、IP層でフラグメント化されやすくなります。
UDPデータグラムがIPフラグメント化された場合、すべてのフラグメントが揃わなければ元のUDPデータグラムを復元できません。
1つでもフラグメントが失われると、そのUDPデータグラム全体が破棄されます。
UDPデータグラム
├─ Fragment 1: 到着
├─ Fragment 2: 消失
└─ Fragment 3: 到着
→ UDPデータグラム全体を復元できない
UDPのフラグメント化は、次のような通信で問題になりやすいです。
| 用途 | 問題になりやすい理由 |
|---|---|
| DNS | 大きな応答がUDPで返ることがある |
| VPN | カプセル化でパケットサイズが大きくなる |
| VoIP | パケットロスや遅延に弱い |
| オンラインゲーム | 遅延やロスが体感品質に直結する |
| 映像配信 | 大きなUDPパケットを使う場合がある |
| QUIC | UDP上で動作するためサイズ設計が重要 |
UDPを使うアプリケーションでは、IPフラグメント化に頼らず、アプリケーション側で安全なサイズに分割する設計が重要です。
VPNやトンネルでは、元のパケットに追加のヘッダーが付与されます。
たとえば、元のIPパケットが1500バイトだった場合、VPNヘッダーが追加されることで、全体サイズが1500バイトを超えることがあります。
元のIPパケット: 1500バイト
+ VPNやトンネルの追加ヘッダー
= 1500バイトを超える
→ フラグメント化、または破棄
VPN環境では、追加ヘッダー分を考慮してMTUを小さく設定することがあります。
例として、VPNインターフェースのMTUを1400〜1420前後に調整するケースがあります。
ただし、適切な値はVPN方式、暗号方式、ネットワーク構成、経路上のMTUによって変わります。
フラグメント化されたパケットは、すべての断片が揃わなければ再構成できません。
そのため、フラグメント数が増えるほど、どれか1つが失われる可能性も高くなります。
たとえば、1つの大きなIPパケットが4つに分割された場合、4つすべてが届かないと元に戻せません。
受信側は、届いたフラグメントを一時的にメモリに保持し、すべての断片が揃うのを待つ必要があります。
大量のフラグメントが届くと、受信側のCPUやメモリに負荷がかかります。
後続フラグメントには、TCPやUDPのヘッダーが含まれないことがあります。
通常、ポート番号などの情報は最初のフラグメントに含まれます。
後続フラグメントだけを見ると、どの通信に属するものか判断しにくい場合があります。
そのため、ファイアウォール、IDS、IPS、NATでは、フラグメントの扱いが難しくなります。
IPフラグメントは、過去から攻撃や検査回避に悪用されてきました。
| 攻撃・問題 | 概要 |
|---|---|
| Tiny Fragment Attack | ヘッダーを細かく分割し、フィルタリングを回避する |
| Overlapping Fragment Attack | 重複するフラグメントを使い、再構成結果の違いを悪用する |
| Teardrop Attack | 不正なオフセットを使い、古いOSや機器をクラッシュさせる |
| Firewall回避 | 重要な情報を後続フラグメントに隠して検査を回避する |
現代のOSやセキュリティ機器では多くの対策がされていますが、フラグメント化がセキュリティ上の注意点であることに変わりはありません。
TCPやUDPのポート番号は、通常、最初のフラグメントに含まれます。
後続フラグメントには、TCP/UDPヘッダーが含まれないことがあります。
Fragment 1:
IPヘッダー + TCPヘッダー + データ前半
Fragment 2:
IPヘッダー + データ後半
Fragment 3:
IPヘッダー + データ残り
この場合、Fragment 2やFragment 3だけを見ても、宛先ポートや送信元ポートを判断できません。
ファイアウォールやIDS/IPSでは、フラグメントを再構成して検査するか、不審なフラグメントを破棄する必要があります。
特に、重複フラグメント、不自然に小さいフラグメント、異常なOffsetを持つフラグメントなどは、攻撃や回避の可能性があります。
Wiresharkでは、IPv4フラグメントを確認する場合、次のような表示フィルタを使えます。
ip.flags.mf == 1 or ip.frag_offset > 0
このフィルタでは、More Fragmentsが立っているパケット、またはFragment Offsetが0より大きいパケットを確認できます。
確認すべき主な項目は次の通りです。
| 項目 | 見るポイント |
|---|---|
ip.flags.mf |
後続フラグメントがあるか |
ip.frag_offset |
元パケット内での位置 |
ip.id |
同じ元パケットに属するか |
frame.len |
実際のフレームサイズ |
Reassembled IPv4 |
Wiresharkが再構成した結果 |
IPv6のフラグメントを確認する場合は、環境やWiresharkのバージョンにもよりますが、次のようなフィルタが使えます。
ipv6.fragment
また、IPv6のFragment Headerを直接確認したい場合は、関連フィールドを確認します。
LinuxやmacOSでIPv4フラグメントを確認する場合、tcpdumpでは次のようなフィルタを使えます。
tcpdump -n -vv 'ip[6:2] & 0x3fff != 0'
対象ホストを絞る場合は、次のようにします。
tcpdump -n -vv host 192.0.2.10 and 'ip[6:2] & 0x3fff != 0'
0x3fff は、MFビットとFragment Offsetの両方を確認するためのマスクです。
なお、次のフィルタはFragment Offsetが0ではないものを拾うため、2番目以降のフラグメントは検出できますが、最初のフラグメントを取り逃がす可能性があります。
tcpdump -n -vv 'ip[6:2] & 0x1fff != 0'
IPv4フラグメント全体を確認したい場合は、0x3fff を使う方が適切です。
Linuxでは、DFフラグ付きでpingを送ることで、MTU問題を調べることができます。
ping -M do -s 1472 example.com
IPv4の場合、ICMPペイロード1472バイトに、ICMPヘッダー8バイト、IPv4ヘッダー20バイトを足すと、合計1500バイトになります。
ICMPペイロード 1472
+ ICMPヘッダー 8
+ IPv4ヘッダー 20
= 1500
サイズを下げながら試すことで、経路上で通過できる実効MTUを推定できます。
ping -M do -s 1464 example.com
ping -M do -s 1452 example.com
ping -M do -s 1400 example.com
Windowsでは、次のように指定します。
ping example.com -f -l 1472
-f はDFフラグを設定するオプションです。
-l はICMPペイロードサイズを指定するオプションです。
pingによるMTU確認は便利ですが、万能ではありません。
| 注意点 | 内容 |
|---|---|
| ICMPが遮断される場合がある | pingが失敗してもMTU問題とは限らない |
| 実通信と経路が違う場合がある | TCPやUDPの通信とは挙動が異なることがある |
| IPv4とIPv6で計算が異なる | ヘッダーサイズが違う |
| 宛先が応答しない場合がある | サーバー側でICMP応答を無効化していることがある |
pingはあくまで調査の一手段として使うのが適切です。
フラグメント化はIPの仕様に含まれる正規の仕組みです。
しかし、実務上は性能・安定性・セキュリティの観点から、できるだけ避けるべきものと考えられることが多いです。
主な理由は次の通りです。
・1つでも断片が失われると元パケットを復元できない
・受信側のCPUやメモリ負荷が増える
・ファイアウォールやNATと相性が悪い場合がある
・攻撃や検査回避に悪用されることがある
・VPNやトンネル環境でトラブルになりやすい
そのため、現代のネットワーク設計では、
大きなパケットを途中で分割して通す
よりも、
最初から経路に合ったサイズで送る
ことが重要です。
フラグメント化を避けるための代表的な対策は次の通りです。
| 対策 | 内容 |
|---|---|
| 適切なMTU設定 | VPNやトンネルでは追加ヘッダーを考慮してMTUを調整する |
| TCP MSS clamping | TCP MSSを経路に合わせて小さく調整する |
| PMTUDを有効にする | 経路上のMTUを検出して送信サイズを調整する |
| ICMPを過剰に遮断しない | PMTUDに必要なICMPエラーを通す |
| UDPペイロードを小さくする | アプリケーション側で安全なサイズに分割する |
| セキュリティ機器で適切に処理する | 不審なフラグメントを検査・破棄する |
小さなHTMLは表示されるのに、大きな画像、JavaScript、CSS、APIレスポンスなどで読み込みが止まる場合、MTU問題が関係していることがあります。
特にVPN経由やクラウド間接続で起こりやすい症状です。
VPNでは追加ヘッダーによって実効MTUが下がります。
そのため、通常のネットワークでは問題がなくても、VPN経由になるとパケットサイズが大きすぎて通信が不安定になることがあります。
DNSでは、応答サイズが大きくなるとUDPパケットが大きくなります。
その結果、IPフラグメント化が発生し、途中のファイアウォールがフラグメントを落とすことで名前解決に失敗することがあります。
SSHのログインや小さなコマンドは通るのに、ファイル転送や大きな出力で止まる場合、MTUやPMTUDブラックホールが関係している可能性があります。
フラグメント化されたパケットとは、MTUを超える大きなIPパケットが、複数の小さなIPフラグメントに分割されたものです。
重要なポイントは次の通りです。
| ポイント | 内容 |
|---|---|
| 発生理由 | パケットサイズが経路上のMTUを超えるため |
| 主な対象 | IP層 |
| IPv4 | 送信元または途中ルーターがフラグメント化する場合がある |
| IPv6 | 途中ルーターはフラグメント化せず、送信元が行う |
| 再構成 | 基本的に受信先ホストで行う |
| Offset | IPv4では8バイト単位 |
| TCP | MSSによりフラグメント化を避けやすい |
| UDP | 大きなデータグラムではフラグメント化が問題になりやすい |
| 実務上の方針 | できるだけフラグメント化を避ける |
フラグメント化は正規の仕組みですが、安定した通信設計ではできるだけ発生させない方が安全です。
特に、VPN、PPPoE、IPsec、GRE、クラウド間接続、コンテナネットワーク、UDPベースの通信では、MTUとMSSの設計が重要です。
一言でまとめると、フラグメント化されたパケットとは、大きすぎるIPパケットをネットワークに通すために分割したものです。
ただし現代のネットワーク運用では、フラグメント化に頼るのではなく、Path MTU Discovery、MSS clamping、MTU調整、UDPペイロード制御などによって、最初から経路に合ったサイズで送ることが重要です。
以上、フラグメント化されたパケットについてでした。
最後までお読みいただき、ありがとうございました。