ICMP (Internet Control Message Protocol) は、IP ネットワーク上で発生したエラーや経路状態を通知するための制御プロトコル。データ自体を運ぶのではなく、「届かなかった」「TTL が切れた」「ポートが閉じている」といった情報を送信元に返すことで、ホストとルータが状況を判断できるようにする。ping と traceroute はすべてこの上で動く。RFC 792 (IPv4) で定義され、IPv6 では ICMPv6 (RFC 4443) として再設計された。
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 byte | ICMP メッセージ全体の検証用 |
| Rest of Header | 4 byte | Type ごとに用途が異なる (Echo の Identifier+Sequence など) |
| Data | 可変 | エラー通知系は「失敗した IP パケットの IP ヘッダ + 先頭 8 byte」を返す |
エラー通知系メッセージが 失敗した元パケットの一部 を返してくれるおかげで、送信元は「どの送信パケットがどう失敗したか」を識別できる。tcpdump で ICMP を見るときは Type/Code に加えて、内側に挟まっている元 IP ヘッダ (Source/Dest IP, TCP/UDP ポート) を読むと原因がわかる。
ping と traceroute は何をしているのか #
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 で理由が分かる
- TTL exceeded (Type 11) が返る → 経路ループまたは TTL を異常に低く送ってしまった
Web サーバが ICMP だけブロックしている運用は普通にある。Echo Reply が無くても TCP 443 は生きていることが多い。
traceroute は TTL を 1 ずつ上げて Time Exceeded を集める #
traceroute は TTL=1, 2, 3, ... と上げながらプローブを送り、各中継ルータが返す Time Exceeded (Type 11) を集計して経路を描く。最終ホストでは Type 11 が返らないので、別の合図でゴール判定する。
tracert / Linux -I): Echo Reply (Type 0) で到着。TCP SYN 版 (-T / tcptraceroute): 80/443 で FW を抜けて経路追跡。自分で動かして確かめる — TTL を 1 ずつ上げると、経路上のルータが 1 ホップずつ Time Exceeded を返して可視化される様子を 1 ステップずつ追える。
途中の * * * は、そのホップのルータが Time Exceeded を返さない (またはレート制限している) ことを意味する。多くのルータは ICMP 生成をレート制限しているので、ホップが消えること自体は珍しくない。
現場で読むメッセージ #
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 で必須 (次節) |
| 9 | Network Administratively Prohibited | ACL で網単位拒否 |
| 10 | Host Administratively Prohibited | ACL でホスト単位拒否 |
| 13 | Communication Administratively Prohibited | FW で遮断 |
Code 3 (Port Unreachable) は UDP プローブの応答としてよく見る。dig で名前解決失敗のハマりの原因にもなる。Code 13 は明示的に FW で蹴られた合図なので、ネットワーク側の設定責任者に確認が必要。
Time Exceeded (Type 11) #
| Code | 意味 |
|---|---|
| 0 | TTL Exceeded in Transit (中継で TTL=0 になった) |
| 1 | Fragment Reassembly Time Exceeded (フラグメント再構成タイムアウト) |
Code 0 は traceroute の合図でもあるが、運用で連発する場合は経路ループを疑う。
Redirect (Type 5) #
ルータがホストに「もっと良い経路がある」と通知する。偽装されると中間者攻撃に使えるため、現代の OS は既定で受け入れない (後述)。
- Source Quench (Type 4) — RFC 6633 (2012) で廃止。輻輳制御は TCP ECN に任せる
- Timestamp (Type 13/14) — NTP に置き換わった。uptime fingerprinting に悪用されるので外向きはドロップが定石
- Address Mask Request (Type 17/18) — DHCP で代替済み
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 レスポンスだけタイムアウトする」といった 最も再現性が悪い障害 の典型的な原因。
「ICMP は全部止めれば安全」という設定が、最も嫌な障害を生む。Type 3 Code 4 (Fragmentation Needed) は inbound / outbound 両方で必ず通すのが鉄則。回避策として TCP MSS Clamping (ルータ側で SYN の MSS を強制的に下げる) を入れる手もある。VPN や PPPoE 環境ではほぼ必須の設定。
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 相当のマルチキャスト管理 |
NDP も RA も動かなくなる。フィルタリング設計は RFC 4890 が必読 — どの Type を落としていいか・絶対に通すべきかが整理されている。ブラックリスト方式 (落とすものを明示) で運用するのが安全。
セキュリティで押さえる点 #
歴史的に Smurf や Ping of Death が話題になったが、現代の OS とルータでは対策済み。今意識すべきは以下の 4 点。
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=0ICMP tunneling (covert channel) #
Echo Request / Reply のペイロードに任意データを詰めて、TCP/UDP の通信を ICMP に偽装して FW を抜ける 手法。icmpsh や ptunnel が代表例で、APT 攻撃で C2 通信に使われた事例もある。
検知のポイント:
- 異常に大きい / 連続する Echo パケット (普通の ping は 64 byte 程度)
- 応答のない一方向 Echo (内部→外部だけが大量)
- サーバから外向き ICMP の流量を Egress firewall で監視
OS フィンガープリンティング #
ICMP 応答の細部 (TTL 初期値、Code の選択、応答可否) に OS 固有の癖 が出るため、nmap -O の手がかりになる。インターネットに直接面するホストでは、Timestamp (Type 13/14) を落とすだけでも偵察情報を減らせる。
Ping flood / rate limiting #
ICMP Echo を大量に送りつける単純な DoS。Linux カーネル / ルータ側で icmp_ratelimit を設定し、FW で Echo Request を limit モジュール経由にしておくのが定石。
フィルタリング戦略 — 全許可も全拒否も両方危険 #
「ICMP は全部止めれば安全」は誤り。PMTUD が壊れ、診断もできなくなる。選択的に許可するのが正しい。
| Type | 通す/落とす | 理由 |
|---|---|---|
| Destination Unreachable Code 4 | 必ず通す (in/out) | PMTUD 必須 |
| Destination Unreachable 他 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) | 落とす | 廃止済み |
# 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 DROPICMP は地味だが、通信が壊れた瞬間に最初の情報を運んでくれるプロトコル。トラブル切り分けで ping / traceroute / mtr を打つときに「返ってきたのが Type 3 か 11 か、Code は何か」まで見るだけで、原因への距離が一気に縮まる。「とりあえず ICMP ブロック」をやめて、Code 4 (PMTUD) と Time Exceeded だけは絶対に通す設計に変えるのが、運用とセキュリティの両立への第一歩。