---
title: ICMP と PMTUD
url: https://doc.liz6.com/ja/networking/02-l3-network-layer/03-icmp-and-pmtud
locale: ja
area: networking
tags:
- networking
- l3-network-layer
date: 2026-06-30
modified: 2026-07-16
description: インターネットの制御面——ICMPはpingだけでなく、PMTUD（パスMTU発見）のエンジンであり、ルーティング不能フィードバックチャネルでもあります。PMTUDの「ブラックホール」障害——ファイアウォールによるICMPの遮断がTCPのハングを引き起こす——は、L2-L4の境界における最も古典的なトラブルシューティング事例です。
---

# 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*
