【実務・中級編】 ICMP到達不能メッセージ(Destination Unreachable)のサブコード – ネットワーク基礎とWebセキュリティ実践ガイド

「通信できない」の解像度を上げろ:ICMP Destination Unreachableが語るネットワークの真実

ネットワークエンジニアとして現場に立っていると、若手から「Web APIがタイムアウトするんです」と相談を受けることがよくあります。そんな時、私は決まってこう返します。「そのタイムアウト、本当に通信が『届いていない』のか? それとも『拒絶されている』のか?」

パケットロスはネットワークの日常茶飯事ですが、ただ沈黙するだけでなく、ルーターやホストがわざわざ「お前、そこには行けないよ」と教えてくれるメッセージがあります。それが ICMP Destination Unreachable です。今回は、このエラーが伝える「サブコード」という名のヒントを読み解き、泥沼のトラブルシューティングから脱出する術を解説しましょう。

ICMP Destination Unreachable とは何か

ICMP Destination Unreachable(タイプ3)は、送信元が送ったパケットが最終目的地に到達できなかった際、途中のルーターや宛先ホストから発せられる「悲報」です。重要なのは、これが単なるエラーコードではなく、「なぜダメだったのか」を詳細に分類したサブコードを持っている点です。

これを理解しておくと、障害発生時にパケットキャプチャを眺めるだけで、「ああ、これはファイアウォールの設定ミスだな」あるいは「宛先のサービスが落ちているな」と、即座に当たりがつけられるようになります。

主要なサブコードの正体

現場で特に遭遇頻度が高いサブコードを整理しましょう。

  • Code 0 (Net Unreachable): ルーターのルーティングテーブルに宛先ネットワークへの経路がない。
  • Code 1 (Host Unreachable): ネットワークまでは届いたが、宛先のホストが見当たらない(ARP解決失敗など)。
  • Code 3 (Port Unreachable): ホストには届いたが、指定されたポートでリスニングしているプロセスが存在しない(UDPで顕著)。
  • Code 4 (Fragmentation Needed and DF set): パケットサイズが大きすぎて、ルーターを通過できない(MTU問題)。

現場のトラブルシューティング:パケットの「言い分」を聞く

例えば、APIサーバーに対して curl を叩いたのにレスポンスが返ってこない場合、まずはその「沈黙の理由」を探ります。

1. curl で確認する(疎通確認の基本)

単純な疎通確認なら -v (verbose) オプションが最強です。

# 宛先ポートを指定して疎通確認
curl -v http://192.168.1.50:8080

# もしPort Unreachableが返ってくれば、
# サーバー側でプロセスが死んでいるか、
# ファイアウォールがREJECT(ICMPを返す設定)している可能性が高い

2. Python でエラーをキャッチする

API開発において、requests を使っているなら例外処理でこのエラーをハンドリングすることも可能です。ただし、OSレベルで ICMP Destination Unreachable を受信すると、ソケットは ConnectionRefusedError を送出します。

import requests
from requests.exceptions import ConnectionError

url = "http://192.168.1.50:8080"

try:
    response = requests.get(url, timeout=5)
    response.raise_for_status()
except ConnectionError as e:
    # 接続拒否や到達不能の場合、ここに落ちる
    print(f"通信に失敗しました: {e}")
    # 実際にはここでログを精査し、ICMPパケットが飛んできていないか確認する

トラブルシューティングの極意:MTUとフラグメンテーション

ここが一番の「罠」です。VPN経由やクラウドのオーバーレイネットワークを使っていると、Code 4 (Fragmentation Needed) に遭遇します。

「特定の大きなファイル転送だけ失敗する」「APIで長いリクエストを送ると切れる」といった事象は、MTUの不一致が原因である可能性が高い。この時、ルーターは「分割したいけど、パケットに DF (Don’t Fragment) フラグが立ってるから無理だよ!」とICMPで伝えてくれています。

解決策: 経路上のMTUサイズを特定し、クライアント側で調整します。

# LinuxでMTUサイズを調査(-M do でDFフラグを強制)
# サイズを徐々に下げながら、成功するポイントを探る
ping -M do -s 1472 192.168.1.50

# これが失敗し、1400だと成功するならMTUは1400以下にする必要がある

最後に:ネットワークを「透明」にするために

ネットワークセキュリティに携わるエンジニアにとって、これらのICMPメッセージは「敵」ではなく「道標」です。セキュリティポリシーとして「外部からのスキャンを隠蔽するためにICMPを全拒否(DROP)する」という設計も一般的ですが、トラブルシューティングの観点からは、適切に REJECT を返す設計の方が、運用コストは劇的に下がります。

パケットがネットワーク上をどう駆け巡り、どこで弾かれ、どのような悲鳴(ICMP)を上げているか。それを想像できる力が、あなたを真のエンジニアへと押し上げます。

コマンドを打つ前に、まずはパケットの気持ちになって「今、どこで何が起きているのか?」をイメージしてみてください。その習慣こそが、最速の障害復旧への近道です。

コメント

タイトルとURLをコピーしました