このページの目次

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