このページの目次
ICMP と PMTUD
インターネットの制御面——ICMPはpingだけでなく、PMTUD(パスMTU発見)のエンジンであり、ルーティング不能フィードバックチャネルでもあります。PMTUDの「ブラックホール」障害——ファイアウォールによるICMPの遮断がTCPのハングを引き起こす——は、L2-L4の境界における最も古典的なトラブルシューティング事例です。
概要
ICMP(Internet Control Message Protocol)は、IPプロトコルの診断および制御補助レイヤーです。これはトランスポートプロトコルではなく、アプリケーションデータを転送するものではなく、ネットワークデバイス間でエラー(到達不能、タイムアウト)を報告し、情報を交換(echo要求/応答)するためのチャネルです。pingとtracerouteは最も一般的なICMPツールです。PMTUD(Path MTU Discovery)は、ICMPの「フラグメンテーション必要」メッセージを利用して、送信側がパス上の最小MTUを知ることを可能にします。これは盲目的なフラグメンテーションよりも効率的ですが、ICMPがファイアウォールでフィルタリングされると、サイレント障害(MTUブラックホール)を引き起こす可能性があります。
ICMPv4 メッセージ構造
ICMPはIPの附属プロトコルです (protocol=1, IPパケットにカプセル化):
[IPヘッダ | ICMP Type (1B) | Code (1B) | Checksum (2B) | ICMPボディ]
Typeの主要カテゴリ:
0: Echo Reply
3: Destination Unreachable (codes: 0=Net, 1=Host, 3=Port, 4=Frag Needed, 13=Administratively Prohibited)
5: Redirect (codes: 0=Net, 1=Host)
8: Echo Request (ping)
11: Time Exceeded (codes: 0=TTL expired in transit, 1=Fragment reassembly timeout)
12: Parameter Problem (codes: 0=IP header bad, 1=Required option missing)
Destination Unreachable (type 3)
code 4 (Fragmentation Needed) が最も重要です——これが PMTUD の唯一のシグナルです:
RFC 1191 は code 4 のメッセージボディを拡張しました:
[unused 2B][Next-Hop MTU 2B][元のIPヘッダ + ペイロードの最初の8B]
→ Next-Hop MTU = 次ホップのMTU (例: PPPoEの場合 1492)
→ 元のIPヘッダ + 最初の8B → 送信側はどの接続に該当するかを特定できます
ping
Echo Request (type 8) → Echo Reply (type 0):
識別子 (2B): 通常 = プロセスPID (Unixのping) — replyとrequestをマッチングするために使用
シーケンス番号 (2B): 増分 (各プローブごとに +1)
Data: 可変 (Unix: デフォルト 56B, ICMPヘッダを含むと 64B にパディング)
TTL の解釈:
$ ping 1.1.1.1 → reply: ttl=57
→ 初期TTL (このホストのデフォルト) = 64 (Linux)
→ 64 - 57 = 7ホップ先
$ ping 1.1.1.1 → reply: ttl=119
→ 送信者の初期TTL = 128 (Windows)
→ 対象OSを推測可能: Linux/Unix = 64, Windows = 128, Solaris = 255
ping -M do (DFビット):
PMTUDのテスト: 大きなパケットを送信 + DF=1 → パス上のどこかでMTU < パケットサイズの場合 → Frag Needed またはタイムアウト
traceroute
TTLを段階的に増加させる → 各ホップでICMP Time Exceeded (type 11, code 0) を返す:
traceroute 1.1.1.1:
Probe 1: TTL=1, UDP宛先ポート 33434 → Router_1 が破棄 + ICMP Time Exceeded を返信
Probe 2: TTL=2, UDP宛先ポート 33435 → Router_2 が破棄 + ICMP Time Exceeded を返信
Probe 3: TTL=3, UDP宛先ポート 33436 → 宛先 (1.1.1.1): ポート到達不能 (ICMP Port Unreachable)
→ 終了
各ホップで3プローブ: 各ホップのマルチパスを検出 (異なる3つのIPが異なるパスに対応している可能性あり)
IPv6 traceroute: UDP または ICMPv6 Echo を使用し、メカニズムは同じ
PMTUD: 完全なフロー
送信側: TCP接続 to server, MSS=1460, DF=1
1. サーバーが送信するパケット: size=1500B (MSS 1460 + TCPヘッダ 20 + IPヘッダ 20)
2. 中間ルーター: インターフェースMTU = 1492 (PPPoE) → パケット破棄 + ICMP Frag Needed (code 4, MTU=1492)
3. 送信側: ICMPを受信 → ルートキャッシュのPMTUを 1492 に更新 → 小さなパケットで再送信 (MSS 1452 = 1492 - 40B TCP+IP)
4. 以降のパケット: MSS=1452 → PMTUDをトリガーしない
PMTU キャッシュ:
ip route get <dst> → cache mtu xxx
Linux: ルートごとのPMTU, 10分経過で期限切れ → 期限切れ後に再検出
ブラックリスト:
TCP MTUプロービング: tcp_mtu_probing=1 → TCP再送が連続して発生した場合、
自動的にMSSを縮小しようとする (ICMP待機不要、ICMPフィルタリング対策)
sysctl net.ipv4.tcp_mtu_probing=1
IPv6 PMTUD (RFC 8201):
原理は同じ、ICMPv6 Packet Too Big (type 2, code 0)
ただしIPv6ヘッダは固定40B → MTU計算がより単純
参考
- RFC: 792, 4443, 1191, 8201
- ツール:
ping -M do,traceroute -T -p 443(TCP),tracepath,mtr - ソースコード:
net/ipv4/icmp.c,net/ipv6/icmp.c
キーワード: ICMP, Destination Unreachable, ping, traceroute, PMTUD, Frag Needed, MTU black hole, MSS clamping