【入門編】 ICMPv4メッセージタイプとコードの分類 – ネットワーク基礎とWebセキュリティ実践ガイド

こんにちは!ネットワークセキュリティの世界へようこそ。

日々、Webサイトをブラウジングしたり、アプリでデータを取得したりするとき、私たちの裏側では無数のパケットが世界中のネットワークを駆け巡っています。しかし、時にはルーターが故障していたり、宛先のサーバーが存在しなかったりして、パケットが迷子になってしまうこともありますよね。

そんな時、「パケットの配達員」であるルーターやサーバーは、ただ黙ってパケットを捨てるわけではありません。「すみません、宛先が見つかりませんでした!」「途中で寿命が切れました!」という緊急アラートを差出人に送り返してくれるのです。

この「ネットワークの悲鳴や返事」を届ける仕組みこそが、今回テーマにするICMPv4(Internet Control Message Protocol version 4)です。

一見すると「小難しそうな英語と数字の羅列」に思えるかもしれませんが、仕組みは驚くほど現実世界の「郵便配達」とそっくりです。今回は初心者や新米インフラエンジニアの皆さんに向けて、パケットがネットワークを旅するドラマを感じながら、ICMPメッセージの基本構造と代表的なエラー通知(Type 3 や Type 11 など)の正体を一歩ずつ紐解いていきましょう!

—

1. そもそもICMPってどんな役割?(IPの頼れる相棒)

私たちが普段使っている IP(Internet Protocol) というプロトコルは、実は「ベストエフォート(できうる限りの努力はするけれど、届く保証はしない)」というちょっと大雑把な性格をしています。IPパケットは、自分自身が途中で落ちたり消えたりしても、それを送信元に報告する機能を持っていません。

そこで登場するのが、IPの「お世話係」である ICMP です。

郵便に例えてみましょう。

  • IPパケット = 宛先が書かれた「手紙」
  • ルーター = 各地域の「郵便局・配達員」
  • ICMP = 手紙が届かなかった時に郵便局から届く「不在票」や「配送不能通知ハガキ」

もし宛先の家が取り壊されていたら、配達員さんは手紙を捨てて終わりにするのではなく、「宛先不明のため返送します」というハガキを差出人に送りますよね。まさにこのハガキの役割を果たしているのが ICMP なのです。

—

2. ICMPメッセージの構造:「Type」と「Code」の組み合わせ

ICMPのメッセージは、非常にシンプルで洗練された構造をしています。難しいビット数やヘッダーのオフセットを丸暗記する必要はありません。まずは「大分類(Type)」と「小分類(Code)」の2つの組み合わせでメッセージが作られていることだけを覚えてください!

  • Type(タイプ):何が起きたのか?(大まかな見出し/赤スタンプ)
  • Code(コード):なぜそれが起きたのか?(詳しい理由/手書きの補足メモ)

例えば、郵便の例で言うなら、ハガキに押された大きな「配送不能」という赤スタンプが Type で、「表札がないため」「転居先不明のため」といった細かい理由が Code にあたります。

ICMPヘッダーのイメージ構造

0                  8                  16                               31 bit
+-------------------+-------------------+---------------------------------+
|   Type (タイプ)   |    Code (コード)  |       Checksum (チェックサム)   |
+-------------------+-------------------+---------------------------------+
|            メッセージ固有のデータ (Identifier, Sequence number等)       |
+-------------------------------------------------------------------------+
|      エラー発生時の「元のIPヘッダー + 元のデータの先頭8バイト」          |
+-------------------------------------------------------------------------+

注目してほしいのは一番下の部分です!エラーを通知する ICMP メッセージには、「どのパケットが原因でエラーになったか」が分かるように、送信した元のIPヘッダーの一部がそっくりそのまま添付されて返ってきます。これがあるおかげで、送信元は「あ、さっき送信したあの通信が失敗したんだな」と正確に把握できる仕組みになっているのです。親切ですよね!

—

3. 絶対に覚えておきたい!主要なICMPメッセージ

ICMPにはたくさんの種類がありますが、現場で日常的に出会うのはほんの数種類です。まずは以下の代表選手たちをマスターしましょう。

① Type 8 / Type 0:Echo Request( echo 要求) & Echo Reply( echo 応答)

みんな大好き ping コマンドで使われるメッセージです。

  • Type 8(Code 0):ネットワークの相手に向かって「おーい、聞こえますかー?」と呼びかける(Echo Request)
  • Type 0(Code 0):受け取った相手が「はい、聞こえてますよー!」と打ち返す(Echo Reply)

やまびこのようなシンプルなやり取りで、相手が生きて存在しているか(生死確認)を診断します。

—

② Type 3:Destination Unreachable(到達不能)

パケットが何らかの理由で目的地に届かなかったときに、ルーターやサーバーから返される「ごめんなさい、届けられませんでした」という通知です。

この Type 3 は、Code(詳細な理由)がとっても重要になります!代表的なものをいくつか見てみましょう。

| Type | Code | 名称 | どんな状態?(人間味あふれる解説) |
|—|—|—|—|
| 3 | 0 | Net Unreachable | 「そのネットワークへ行く道(ルーティング情報)がルーターに見つかりませんでした!」 |
| 3 | 1 | Host Unreachable | 「目的のネットワークには着いたけど、該当するIPアドレスの機器が存在しません!」 |
| 3 | 3 | Port Unreachable | 「機器には届いたけど、指定されたポート番号(受付窓口)が開いていませんでした!」 |
| 3 | 4 | Fragmentation Needed and DF set | 「パケットが大きすぎてルーターを通れません!でも『分割禁止(DFフラグ)』がセットされているので破棄しました!」 |

特に Type 3 / Code 4 は、ネットワークエンジニアが遭遇する「Webページが途中までしか開かない」といったMTU(パケットの最大サイズ)トラブルの解析で非常に重要な鍵となります。

—

③ Type 11:Time Exceeded(時間切れ / TTL超え)

ネットワークパケットには、ルーターを1台経由するごとに「1」ずつ減っていく寿命カウントダウン値(TTL / Time To Live)が設定されています。もしルーティングループ(ルーター間でパケットがぐるぐる無限ループすること)が発生しても、パケットがインターネット上を永遠に彷徨わないようにするための安全装置です。

この TTL が 0 になった瞬間、ルーターはパケットを破棄し、送信元へ Type 11 (Code 0: Time to Live exceeded in Transit) を返します。

『traceroute』コマンドの美しい仕掛け

実は、ネットワークの経路を調べる traceroute(Windowsでは tracert)というコマンドは、この Type 11 の仕組みをあえて逆手に取った天才的なツールなのです!

1. 最初のパケットの TTL を 1 にして送信する ➔ 1台目のルーターで TTL=0 になり、Type 11 が返ってくる(これで1台目のルーターのIPが判明!)
2. 次のパケットの TTL を 2 にして送信する ➔ 2台目のルーターで TTL=0 になり、Type 11 が返ってくる(これで2台目のルーターのIPが判明!)
3. これを繰り返し、目的地までの「旅のルート」をあぶり出していく。

仕組みを知ると、なんだかワクワクしてきませんか?

—

4. 現場のパケットを観察してみよう!(実践ハンズオン)

言葉での解説だけでなく、実際のコマンドとパケットの挙動を見ていきましょう。

Linuxのターミナルを使って、tcpdump コマンドでパケットをキャプチャしながら、存在しないIPアドレスへ通信を試みた時の様子を再現してみます。

ターミナルでのパケットキャプチャ例

まずは、裏でICMPパケットを監視(キャプチャ)するコマンドを実行しておきます。

# ICMPパケット(プロトコル番号1)だけをリアルタイムで表示するコマンド
# -i eth0: 監視するネットワークインターフェースを指定
# -nn: IPアドレスやポート番号を名前解決せずに数字のまま表示
sudo tcpdump -i eth0 -nn "icmp"

別ウィンドウを開き、存在しないローカルIP(例: 192.168.1.250)に対して ping を打ってみます。すると、tcpdump 側の画面には次のようなリアルなパケットログが流れ出します!

# 1. 存在しないIPに向けて Echo Request (Type 8) を送信
10:00:01.123456 IP 192.168.1.10 > 192.168.1.250: ICMP echo request, id 1234, seq 1, length 64

# 2. 自身のルーター(192.168.1.1)から「Host Unreachable」が返ってくる!
10:00:01.125678 IP 192.168.1.1 > 192.168.1.10: ICMP host 192.168.1.250 unreachable, length 36

ログに出ている unreachable こそが、内部的に Type 3 / Code 1 がやり取りされた証拠です。ルーターが「探し回ったけれど、そのIPの機器は見つからなかったよ!」と丁寧に通知してくれている様子が目に浮かびますね。

Pythonを使った簡単なICMP解析スクリプト

もう少し踏み込んで、送信されてきたICMPの Type と Code をプログラムで読み解くイメージを掴んでみましょう。以下はScapyというライブラリを使った簡単なパケット解析コードの例です。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from scapy.all import sniff, ICMP

def packet_callback(packet):
    """
    キャプチャしたパケットの中にICMPが含まれていた場合に呼び出される関数
    """
    # ICMPレイヤーが存在するかチェック
    if packet.haslayer(ICMP):
        icmp_layer = packet[ICMP]
        
        # ICMPのTypeとCodeを取得
        icmp_type = icmp_layer.type
        icmp_code = icmp_layer.code
        src_ip = packet[1].src
        
        print(f"[+] ICMPパケットを受信しました! 送信元: {src_ip}")
        print(f"    - Type (大分類): {icmp_type}")
        print(f"    - Code (小分類): {icmp_code}")
        
        # 代表的なメッセージの解釈(人間への読み替え)
        if icmp_type == 3:
            print("    --> 判定: Destination Unreachable (宛先達不能です)")
            if icmp_code == 3:
                print("    --> 詳細: Port Unreachable (指定ポートが閉じています)")
        elif icmp_type == 11:
            print("    --> 判定: Time Exceeded (TTLが切れて時間切れになりました)")

print("ICMPパケットの監視を開始します... (Ctrl+Cで停止)")
# ICMPパケットのみをキャプチャするフィルターを設定してループ実行
sniff(filter="icmp", prn=packet_callback, count=5)

このコードを実行すると、パケットの生データから Type と Code という「数字」を取り出し、それが何を意味しているのかをプログラムで判定できることが良く分かります。

—

5. セキュリティスペシャリストからのワンポイントアドバイス

最後に、インフラ設計やファイアウォール構築に携わる皆さんに、現場で極めて重要なゼロトラスト&境界防御のアドバイスをお伝えします。

昔のセキュリティ対策本などには、「攻撃者にネットワーク構造を探られないよう、ICMP はファイアウォールで全てブロック(DROP)しなさい」と書かれていることがありました。しかし、すべてのICMPを遮断するのは現代のネットワークでは「NG(非推奨)」とされています!

なぜなら、前述した Type 3 / Code 4(Fragmentation Needed) まで遮断してしまうと、通信の最適サイズを自動調整する「Path MTU Discovery(経路MTU探索)」が機能しなくなるからです。その結果、「大きなデータ(画像やファイル)を送ろうとした瞬間に通信がピタッと止まって応答がなくなる」という恐ろしいブラックホールルーター現象を引き起こしてしまいます。

望ましいファイアウォール(Linux nftables等)の設定指針

セキュリティを確保しつつ、ネットワークを正常に保つためのスマートな設定例を見てみましょう。

# nftables での設定例(必要なICMPのみを許可するスマートな制御)

# 1. 外部からの不要な Ping 応答(Type 8)は拒否して攻撃の踏み台を防ぐ
nft add rule inet filter input icmp type echo-request drop

# 2. 通信に必須となるエラー通知(Type 3: 到達不能 や Type 11: 時間切れ)は許可する!
nft add rule inet filter input icmp type destination-unreachable accept
nft add rule inet filter input icmp type time-exceeded accept

ネットワークを安全にするということは、「何でもかんでも鍵をかけて閉じ込める」ことではありません。「通信が正常に動くための最低限の標識やアラート(ICMP)は通してあげつつ、過剰な応答だけを制限する」というバランス感覚が、プロのスペシャリストとして非常に大切になります。

—

まとめ:パケットの「悲鳴」に耳を傾けよう!

今回は ICMPv4 メッセージの仕組みについて解説しました。

  • ICMP は、IPパケットが正しく届かない時に状況を教えてくれる「不在票・報告ハガキ」
  • Type で「何が起きたか」、Code で「その詳しい理由」を表す
  • Type 3(Destination Unreachable)は宛先まで届かなかったエラー通知
  • Type 11(Time Exceeded)はパケットの寿命切れ(traceroute でも大活躍!)
  • セキュリティ上、完全に遮断するのではなく、通信に必要なメッセージを見極めて許可することが大切

これからシステムを構築したり障害対応を行ったりする際、もしエラーに出会ったら「あ、今 Type 3 のコード 3 が返ってきたな。ポートが開いていないのかな?」と、ぜひパケットたちの声に耳を傾けてみてください。

パケットの流れやエラーの裏側にあるドラマが見えてくると、ネットワークのトラブルシューティングが格段に面白くなりますよ!一歩ずつ、一緒に強靭なインフラ知識を身につけていきましょう!

コメント

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