IP フラグメンテーションと Path MTU Discovery
大きい通信だけ無言で止まる原因を、原理から切り分けられます。IPv4とIPv6の分割の違い、DFビットとICMPによるPMTUD、ブラックホールとMSSクランピングまでを正確に整理します。
- 1.IPv4 は中継ルータも分割できるが、IPv6 は送信元のみが Fragment 拡張ヘッダで分割する。経路途中での分割は禁止されている。
- 2.PMTUD は DF ビット付きパケットに対する ICMP(v4 の Fragmentation Needed/v6 の Packet Too Big)で経路最小 MTU を学習する。ICMP が遮断されるとブラックホール化する。
- 3.ブラックホール対策の定番は TCP の MSS クランピングで、SYN の MSS オプションを経路 MTU に収まる値へ書き換えて分割自体を回避する。
なぜ分割は「動くのに避けたい」のか
IP は MTU を超えるデータグラムを分割(フラグメント)して運べます。仕組みとしては正しく動きますが、実運用では分割は性能と信頼性の両面で不利です。ここでは MTU とフラグメンテーション の基礎を前提に、IPv4 と IPv6 で分割の責任主体がどう違うか、PMTUD がどのアルゴリズムで経路 MTU を学習するか、そしてなぜ「大きい通信だけ無言で止まる」事故が起きるのかを、ヘッダのビットレベルまで降りて追います。
IPv4 の分割:途中のルータも分割できる
IPv4 では、データグラムが出力リンクの MTU を超えると、そのリンクを持つ中継ルータ自身が分割できます。分割の制御は IPv4 ヘッダの次の3フィールドが担います。
| フィールド | 幅 | 役割 |
|---|---|---|
| Identification | 16ビット | 同一データグラム由来の断片をグループ化する識別子 |
| Flags | 3ビット | DF(分割禁止)と MF(後続あり)。残り1ビットは予約 |
| Fragment Offset | 13ビット | 元データ先頭からの位置を 8バイト 単位で表す |
要点は Fragment Offset が 8バイト単位 であることです。このため最終断片を除く各断片のペイロード長は 8 の倍数でなければなりません。たとえば MTU 1500・IPv4 ヘッダ 20バイトなら 1 断片あたりのペイロードは 1480 バイトまで使え、1480 は 8 の倍数なのでそのまま載りますが、ヘッダにオプションが付くなどして 8 の倍数にならない場合は 8 境界へ切り下げます。受信側は同一の 送信元IP, 宛先IP, プロトコル, Identification の4つ組で断片を束ね、Offset 順に並べて再構成(リアセンブル)します。MF=0 の断片が最後尾を示します。
IP には断片単位の再送がありません。1つの断片が失われると、揃わなかったデータグラム全体が破棄されます。上位が TCP なら全セグメントを再送、UDP なら丸ごと欠落します。分割数が増えるほど「どれか1つを落とす」確率が上がるため、損失率に対して指数的に脆くなります。
再構成は受信ホストの負担も大きく、各データグラムごとに到着途中の断片を保持するバッファとタイマ(既定で 60 秒程度)が必要です。タイマ満了までに揃わなければ破棄し、IPv4 では ICMP Time Exceeded(code 1) を返します。
IPv6 の分割:送信元だけが行う
IPv6 は設計を変え、中継ルータは一切分割しません。経路途中で MTU を超えたら、ルータは破棄して送信元に ICMPv6 を返すだけです。分割が必要なら、送信元が Fragment 拡張ヘッダ(IPv6 のアドレス体系と近隣探索 で触れた数珠つなぎの一種)を挿入して自ら断片化します。
この変更には明確な利点があります。中継ルータは固定 40バイト の基本ヘッダだけを見ればよく、分割のための状態やバッファを持たずに済むため、転送が速く単純になります。代償として、送信元が経路 MTU を事前に知っている前提が必須になり、PMTUD の重要度が IPv4 より一段上がります。
IPv6 は全リンクに最低 1280バイト の MTU を要求します。PMTUD が機能しない最悪ケースでも、送信元は 1280 まで下げれば確実に届けられるという床(フロア)が保証されています。IPv4 の規格上の最小受信サイズ 576 とは別の概念で、IPv6 ではこの 1280 が PMTUD のクランプ下限になります。
Path MTU Discovery のアルゴリズム
PMTUD(RFC 1191/IPv4, RFC 8201/IPv6)は、経路上で分割を起こさずに通せる最小 MTU を学習する手順です。動作の核は「分割するな、無理なら教えろ」という指示にあります。
- 送信元は DF=1(IPv4)または分割しない前提(IPv6)で、出口リンク MTU いっぱいのパケットを送る。
- 途中のルータでパケットが次リンク MTU を超えると、DF のため分割できず破棄する。
- ルータは ICMP で通知する。IPv4 は ICMP Destination Unreachable / Fragmentation Needed and DF set(type 3, code 4)、IPv6 は ICMPv6 Packet Too Big(type 2)。いずれも通れる Next-Hop MTU の値をメッセージに含む。
- 送信元はその値まで PMTU を下げ、以降はそのサイズで送る。階段状に複数ホップを学習することもある。
送信元 ---[MTU1500]--- R1 ---[MTU1400]--- R2 ---[MTU1500]--- 宛先
| 1500バイト/DF=1 を送信
| R1 が破棄し ICMP(Next-Hop MTU=1400) を返す
| PMTU を 1400 に更新して再送 → 到達
学習した PMTU はホスト内の宛先キャッシュに保持し、定期的に再上昇を試みて経路変化に追従します。古い RFC 1191 にはメッセージが Next-Hop MTU を含まない実装に備えた「代表的 MTU 値を順に試す」プラトー表もありましたが、現在の実装はメッセージ内の MTU 値を直接使います。
ブラックホール問題:ICMP を消すと無言で詰まる
PMTUD は ICMP が送信元まで戻ることに全面的に依存します。ところが運用現場では「セキュリティ」を理由に ICMP を一律遮断するファイアウォールが多く、ここで PMTUD ブラックホール が生まれます。
小さいパケット(ping、SYN/ACK、短い HTTP リクエスト)は MTU に収まるので素通りします。一方、MTU を超える大きいパケットはルータで破棄され、それを知らせる ICMP もファイアウォールで消されるため、送信元は永遠にサイズを下げません。結果として「接続は確立するが、大きい応答だけが無言で消えて固まる」という、原因の見えにくい障害になります。トンネルやVPNで MTU が目減りした経路で頻発します。
症状の典型は「TCP の SYN は通る → ハンドシェイク成立 → 最初の大きいデータで停止」です。ICMP を type 別に選別し、少なくとも Fragmentation Needed / Packet Too Big だけは通すのが正しい対処です。受け身の対策として PLPMTUD(RFC 4821/8899) もあり、これは ICMP に頼らず、TCP/QUIC が探索パケットの到達可否(ACK されたか)からブラックホール込みで PMTU を推定します。
MSS クランピング:そもそも分割させない
ブラックホールを根本回避する実務の定番が MSS クランピング です。TCP は接続時の SYN に MSS オプション(このコネクションで受け取れる最大セグメントサイズ)を載せて交換します。TCP と UDP の違い で見たとおり TCP はバイトストリームをセグメント化するため、MSS を MTU に収まる値へ抑えれば IP 分割も PMTUD も不要になります。
クランピングは経路上の機器(ルータ/ファイアウォール)が通過する SYN の MSS 値を書き換える手法です。リンク MTU が判明している経路で、MSS = MTU − IPヘッダ − TCPヘッダ を超える値を見つけたら下げます。
通常 MTU1500 → MSS = 1500 - 20(IPv4) - 20(TCP) = 1460
PPPoE MTU1492 → MSS = 1492 - 20 - 20 = 1452
IPv6 基本 → MSS = MTU - 40(IPv6) - 20(TCP)
# Linux: 出力 SYN の MSS を経路 MTU に自動クランプ(iptables)
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
# 経路の実 PMTU を DF 付き ping で二分探索(IPv4・Linux)
ping -M do -s 1472 example.com # 1472 + 28 = 1500。通れば OK、Frag Needed なら下げる
MSS は TCP のオプションなので、UDP・QUIC・ICMP・IPsec の ESP など TCP 以外には効きません。IPsec の内部構造 のようなトンネルでは、内側を TCP に限れない以上、トンネル境界での適切な MTU 設計と、ICMP(Packet Too Big)を確実に折り返す経路設計が併せて必要です。
再構成を狙う攻撃と防御
分割は攻撃面でもある点を押さえます。代表的な脅威は次のとおりです。
| 攻撃 | 原理 | 対策 |
|---|---|---|
| オーバーラップ(Teardrop 系) | Offset を重ねた断片を送り、再構成時の境界計算をオーバーフローさせ OS をクラッシュ/回避させる | 重なり断片の破棄、再構成スタックの堅牢化、IDS の正規化 |
| 微小断片による検査回避 | L4 ヘッダを2つ目以降の断片に押し込み、先頭だけ見るフィルタを素通りさせる | 最小断片サイズの強制、再構成後に検査するファイアウォール |
| 再構成バッファ枯渇(DoS) | MF=1 の断片だけを大量に送り、揃わない断片でメモリとタイマを食い潰す | ホスト/データグラム単位のバッファ上限・タイマ短縮・レート制限 |
防御の本質は「断片のまま信用せず、再構成してから検査する」ことと、再構成資源に明確な上限を設けることです。とくにフィルタが先頭断片しか見ない実装だと、L4 ポート番号を後続断片へ追い出す 微小断片攻撃 でアクセス制御を抜かれます。IPv6 はこの種の回避を断つため、最初の断片に上位層ヘッダ全体を含むことを必須化し、不正な重なり断片の破棄を規定しています(RFC 8200)。
「IPv4 は中継ルータも分割/IPv6 は送信元のみ」「DF=1 で分割禁止」「IPv4 は Fragmentation Needed(type3 code4)/IPv6 は Packet Too Big(type2)」「IPv6 の最小 MTU は 1280」「ブラックホールの定番対策は MSS クランピング」。この5点は頻出で、ICMP の type/code まで問われることがあります。
切り分けの順序
不可解な「大きい通信だけ詰まる」障害は、次の順で機械的に切り分けられます。
- DF 付き ping で PMTU を二分探索し、どのサイズから落ちるかを特定する。
- 落ちる経路で ICMP Frag Needed / Packet Too Big が戻っているかをパケットキャプチャで確認する。戻っていなければブラックホール。
- TCP なら SYN の MSS 値を観測し、クランピングで意図どおり下がっているかを見る。
- トンネル経路ならカプセル化オーバーヘッドぶん内側 MTU/MSS を下げ、境界の ICMP を通す。
「IPv4 と IPv6 で分割の主体が違う」「PMTUD は ICMP に全依存する」「TCP は MSS で分割そのものを避けられる」の3点を軸に据えると、MTU 起因の沈黙障害をヘッダレベルで説明し切れるようになります。
ネットワーク Article
IP フラグメンテーションと Path MTU Discoveryを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
IP
比較で見る軸
難易度: advanced / カテゴリ: ネットワーク / タグ数: 6
導入後に効く点
PMTUD は DF ビット付きパケットに対する ICMP(v4 の Fragmentation Needed/v6 の Packet Too Big)で経路最小 MTU を学習する。ICMP が遮断されるとブラックホール化する。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- ネットワーク
- タグ数
- 6
判断チェックリスト
- 自社の用途が「IP / フラグメンテーション」に近いか確認する。
- 強みである「IPv4 は中継ルータも分割できるが、IPv6 は送信元のみが Fragment 拡張ヘッダで分割する。経路途中での分割は禁止されている。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。