Internet Control Message Protocol (ICMP) #

Internet Control Message Protocol (ICMP) は、IP ネットワーク上で発生したエラーや経路状態を通知するための制御プロトコル。データ自体を運ぶのではなく、「届かなかった」「TTL が切れた」「ポートが閉じている」といった情報を送信元へ返すことで、ホストとルータが状況を判断できるようにする。ping と traceroute はすべてこの上で動いている。RFC 792 (IPv4) で定義され、IPv6 では ICMPv6 (RFC 4443) として再設計された。
1. ICMP メッセージの読み方 #
ICMP は IP の上位プロトコル (IPv4 で Protocol Number 1, IPv6 で 58) として動く。TCP/UDP のような ポート番号は持たないので、ss や netstat のコネクション一覧には現れない。

ヘッダは非常にシンプル。
| フィールド | サイズ | 役割 |
|---|---|---|
| Type | 1 byte | メッセージ種別 (Echo Request, Destination Unreachable など) |
| Code | 1 byte | Type ごとのサブ種別 (例: Type 3 Code 1 = Host Unreachable) |
| Checksum | 2 bytes | ICMP メッセージ全体の検証用 |
| Rest of Header | 4 bytes | Type ごとに用途が異なる (Echo の Identifier+Sequence など) |
| Data | 可変 | エラー通知系は「失敗した IP パケットの IP ヘッダ + 先頭 8 バイト」を返す |
ポイントは最後の Data 部分。エラー通知系メッセージが失敗した元パケットの一部を返してくれるおかげで、送信元は「どの送信パケットがどう失敗したか」を識別できる。tcpdump で ICMP を見るときは Type/Code に加えて、内側に挟まっている元 IP ヘッダ (Source / Dest IP, TCP ポート) を読むと原因がわかる。
2. ping と traceroute は何をしているのか #
2.1 ping = Echo Request (Type 8) / Echo Reply (Type 0) #
ping は Type 8 を送って Type 0 が返ってくるまでの時間を測る。Identifier + Sequence Number で複数の ping を区別するため、同じホストから同時に複数の ping を打っても正しく対応付けられる。
応答が来ない場合、考えられる切り分けは:
- 何も返らない → 経路上のどこか、または宛先 FW で ICMP がドロップされている
- Destination Unreachable (Type 3) が返る → 経路上のどこかが「届けられない」と明示的に言っている。Code で理由が分かる (§3)
- TTL exceeded (Type 11) が返る → 経路ループまたは TTL を異常に低く送ってしまった
「pingが通らない=死んでいる」とは限らない。Web サーバが ICMP だけブロックしている運用は普通にある。
2.2 traceroute は TTL を 1 ずつ上げて Time Exceeded を集める #
traceroute は TTL=1, 2, 3, ... と上げながらプローブを送り、各中継ルータが返す Time Exceeded (Type 11) を集計して経路を描く。最終ホストでは Type 11 が返らないので、別の合図でゴール判定する:
- UDP 高ポートを送る (Linux/macOS のデフォルト): 最終ホストが Port Unreachable (Type 3 Code 3) を返したら到着
- ICMP Echo を送る (Windows
tracert, Linuxtraceroute -I): 最終ホストが Echo Reply (Type 0) を返したら到着 - TCP SYN を送る (
traceroute -T/tcptraceroute): 80/443 など FW が通すポートで経路追跡できる
「途中の * * * は何?」と聞かれたら、そのホップのルータが Time Exceeded を返さない (またはレート制限している) ことを意味する。多くのルータは ICMP 生成をレート制限しているので、ホップが消えること自体は珍しくない。
3. 現場で読むメッセージ #
3.1 Destination Unreachable (Type 3) — Code で読む #
| Code | 意味 | 現場での解釈 |
|---|---|---|
| 0 | Network Unreachable | ルーティングテーブルにそのネットへの経路がない |
| 1 | Host Unreachable | 経路上の最後のルータが ARP で MAC を引けない |
| 3 | Port Unreachable | UDP で当該ポートが開いていない / UDP traceroute の終端合図 |
| 4 | Fragmentation Needed and DF Set | PMTUD で必須 (§4) |
| 9 | Network Administratively Prohibited | ACL で網単位拒否 |
| 10 | Host Administratively Prohibited | ACL でホスト単位拒否 |
| 13 | Communication Administratively Prohibited | FW で遮断 |
Code 3 (Port Unreachable) は UDP プローブの応答としてよく見る。dig で名前解決失敗ハマりの原因にもなる。Code 13 は明示的に FW で蹴られた合図なので、ネットワーク側の設定責任者に確認が必要。
3.2 Time Exceeded (Type 11) #
| Code | 意味 |
|---|---|
| 0 | TTL Exceeded in Transit (中継で TTL=0 になった) |
| 1 | Fragment Reassembly Time Exceeded (フラグメント再構成タイムアウト) |
Code 0 は traceroute の合図でもあるが、運用で連発する場合は経路ループを疑う。
3.3 Redirect (Type 5) #
ルータがホストに「もっと良い経路がある」と通知する。偽装されると中間者攻撃に使えるため、現代の OS は既定で受け入れない (§6 参照)。
3.4 廃止・無視してよいもの #
- Source Quench (Type 4): RFC 6633 (2012) で廃止。輻輳制御は TCP ECN に任せる。
- Timestamp (Type 13/14): NTP に置き換わった。uptime fingerprinting に悪用されるので外向きはドロップが定石。
- Address Mask Request (Type 17/18): DHCP で代替済み。
4. PMTUD ブラックホール — ICMP を全部止めると壊れる代表例 #
経路上に MTU が小さい区間があると、DF (Don't Fragment) ビット付き IP パケットを送ったルータは Destination Unreachable Code 4 (Fragmentation Needed) を返す。送信元はこれを受けて TCP MSS を下げる ― これが Path MTU Discovery (PMTUD) の仕組み。
ここでファイアウォールが「ICMP は全部ブロック」にしていると、Code 4 も届かなくなり、大きい TCP セグメントだけ静かに消える現象が起きる。
- 小さい HTTP リクエストは通る
- 大きい POST やレスポンスで突然ハング
- 通常の
ping(小さいエコー) は通るので一見正常に見える
これが PMTUD ブラックホールで、「VPN 越しの一部通信だけ詰まる」「特定の API レスポンスだけタイムアウトする」といった最も再現性が悪い障害の典型的な原因。Type 3 Code 4 は必ず通すこと。
回避策として TCP MSS Clamping (ルータ側で SYN の MSS を強制的に下げる) を入れる手もある。VPN や PPPoE 環境ではほぼ必須の設定。
5. ICMPv6 — IPv6 では止めると動かない #
IPv6 では ICMP の役割が大幅に拡張され、IPv6 の動作そのものに不可欠になっている。ARP・IGMP・Router Discovery などが ICMPv6 に統合された。
| 機能 | Type | 役割 |
|---|---|---|
| Neighbor Solicitation | 135 | IPv4 の ARP 相当 — 隣接ノードの MAC を引く |
| Neighbor Advertisement | 136 | 上記への応答 |
| Router Solicitation | 133 | ホストが「ルータは?」と問い合わせ |
| Router Advertisement | 134 | ルータの存在告知 + プレフィックス通知 (SLAAC の核) |
| MLD | 130-132, 143 | IPv4 IGMP 相当のマルチキャスト管理 |
IPv6 で ICMPv6 を全面ブロックすると NDP も RA も動かず、通信そのものが成立しない。フィルタリング設計は RFC 4890 が必読 ― どの Type を落としていいか・絶対に通すべきかが整理されている。
6. セキュリティで押さえる点 #
歴史的に Smurf や Ping of Death が話題になったが、現代の OS とルータでは対策済み。今意識すべきは以下。
6.1 ICMP Redirect の偽装 #
ローカルセグメント上の攻撃者が 偽の ICMP Redirect を送って「私を経由しろ」と誘導する MITM。Linux なら下記で確実に塞ぐ:
sysctl -w net.ipv4.conf.all.accept_redirects=0
sysctl -w net.ipv4.conf.all.send_redirects=0
sysctl -w net.ipv6.conf.all.accept_redirects=0
6.2 ICMP tunneling (covert channel) #
Echo Request/Reply のペイロードに任意データを詰めて、TCP/UDP の通信を ICMP に偽装して FW を抜ける手法。icmpsh や ptunnel が代表例で、APT 攻撃で C2 通信に使われた事例もある。
検知のポイント:
- 異常に大きい / 連続する Echo パケット (普通の ping は 64 byte 程度)
- 応答のない一方向 Echo (内部→外部だけが大量)
- サーバから外向き ICMP の流量を Egress firewall で監視
6.3 OS フィンガープリンティング #
ICMP 応答の細部 (TTL 初期値、Code の選択、応答可否) に OS 固有の癖が出るため、nmap -O の手がかりになる。インターネットに直接面するホストでは、Timestamp (Type 13/14) を落とすだけでも偵察情報を減らせる。
6.4 Ping flood / rate limiting #
ICMP Echo を大量に送りつける単純な DoS。Linux カーネル / ルータ側で icmp_ratelimit を設定し、また FW で Echo Request を limit モジュール経由にしておくのが定石 (§7)。
7. フィルタリング戦略 — 全許可も全拒否も両方危険 #
「ICMP は全部止めれば安全」は誤り。PMTUD が壊れ、診断もできなくなる。選択的に許可するのが正しい。
7.1 通すべきもの / 落としてよいもの #
# 通すべき (inbound / outbound 両方)
- Destination Unreachable (Type 3) Code 4: 必須 (PMTUD)
- Destination Unreachable (Type 3) 他 Code: 通すと運用が楽
- Time Exceeded (Type 11): traceroute / 診断のため
- Echo Request (Type 8): rate-limit して許可 (完全拒否は診断不能)
- Echo Reply (Type 0): 自分が打った ping の返答用
# 落としてよい
- Redirect (Type 5): MITM のリスク
- Timestamp (Type 13/14): 偵察に悪用される
- Address Mask Request (Type 17/18): 用途がない
- Source Quench (Type 4): 廃止済み
7.2 iptables の例 #
# Echo Request は 1 秒あたり 5 個までに制限
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/sec -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# Destination Unreachable と Time Exceeded は全許可
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
# Redirect / Timestamp はドロップ
iptables -A INPUT -p icmp --icmp-type redirect -j DROP
iptables -A INPUT -p icmp --icmp-type timestamp-request -j DROP
7.3 ICMPv6 は RFC 4890 に従う #
IPv6 では NDP・RA・MLD・PMTUDv6 が全部 ICMPv6 のため、ブラックリスト方式 (落とすものを明示) で運用するのが安全。ip6tables で雑に全 drop すると即通信不能になる。
ICMP は地味だが、通信が壊れた瞬間に最初の情報を運んでくれるプロトコル。トラブル切り分けで ping/traceroute/mtr を打つときに「返ってきたのが Type 3 か 11 か、Code は何か」まで見るだけで原因への距離が一気に縮まる。「とりあえず ICMP ブロック」をやめて、Code 4 (PMTUD) と Time Exceeded だけは絶対に通す設計に変えるのが、運用とセキュリティの両立への第一歩になる。