ICMP(ping)のポート番号は? NAPT越え

ネットワーク

Twitterでとあるツイートを見つけて気になったので。
「pingのポート番号」について。

ICMP(ping)について

結論から言うとICMPにポート番号はない

ポート番号とはOSI参照モデルにおいてトランスポート層(L4)にて利用されるフィールドであり、
ネットワーク層(L3)のIPで受け取ったパケットを上位のアプリケーションとつなげる役割を担う。

それに対し、ICMPはネットワーク層(L3)で動作するプロトコル。
つまりポート番号は存在しない。
ICMPの役割はL3レベルの通信において、様々なエラーの通知や疎通を確認することであり、
IPの拡張プロトコルとして利用される。

IPヘッダは20バイトあり、その後にICMPが続く。

ICMPヘッダにはタイプコードチェックサムが含まれている。
チェックサムはその名の通り、誤り検出に利用される。
タイプ、コードについてはICMPの種類を特定するのに利用される。

タイプコード内容
0 Echo Reply0 Echo Replyエコー応答
3 Destination Unreachable0 Network unreachable宛先ネットワークに到達不能
1 Host unreachable宛先ホストに到達不能
2 Protocol unreachableプロトコルに到達不能
5 Redirect0 Redirect for networkリダイレクト
1 Redirect for hostリダイレクト
8 Echo Request0 Echo Requestエコー要求
ICMPタイプ/コードの一部

これら以外にもたくさんあるが、様々なエラーの通知を行うことができる。
今回はこの中でもpingで使われるEcho Reply, Echo Requestについて詳しく確認する。

NAPT

NAPTは一般家庭で最もよく利用される機能の一つ。
自宅には1つのグローバルIPアドレスが来ているが、家の中にある機器は一つじゃない。
家の中の機器はプライベートIPアドレスを利用するがインターネット上で利用できないため、
プライベートIPとグローバルIPをn:1で紐付ける必要がある。
そこでその役割を担うのがNAPT。

NAPTは(Network Address Port Translation)というようにポート番号を利用する。
NAPTが動くルータにNATテーブルが存在し、そこに内部ポート番号、内部IPアドレス(クライアントPC)、外部ポート番号、外部IPアドレスの組み合わせで追加する。
これで帰ってきたパケットはクライアントPCに送り届けることができる。

しかし、ここで一つ疑問に感じた。

ポート番号のないICMPはどのようにクライアントを識別する?

ICMPにはポート番号がなく、NAPTはポート番号を利用する。
しかし、WindowsからGoogleのDNS(8.8.8.8)にpingを行えば応答がある。

ということは、ICMPの場合はポート番号以外の識別方法があるはず。
ここについてパケットキャプチャを行いながら確認する。

検証

今回はシンプルな構成。
R1にNAPTの設定を入れ、インターネットにはグローバルIPは10.1.1.1とする。(プライベートだが)

R1の設定

//NAPTの設定(IPは割当済み)
#int g0/0
#ip nat inside
#int g0/1
#ip nat outside

//ACLの設定
#ip access-list standard LAN
#permit 192.168.1.0 0.0.0.255

#ip nat inside source list LAN interface g0/1 overload

NAPTの設定が完了したら次は実際にパケットをキャプチャしてみる。

CentOSのインターフェース

R1のG0/1

NAPTが動作して、IPアドレスが192.168.1.1→10.1.1.1に書き換えられている。

次にキャプチャ内容を同時に表示してみる。
同じEcho Requestの共通点を探してみる。

ICMPの中にIdentifierという項目を発見。
この値がルータ上でポート番号の代わりとなっていることが分かった。

ルータ上でNATエントリを確認する方法もあった。

R1#show ip nat translations verbose
Pro Inside global      Inside local       Outside local      Outside global
icmp 10.1.1.1:21338    192.168.1.1:21338  8.8.8.8:21338      8.8.8.8:21338
    create 00:00:08, use 00:00:07 timeout:60000, left 00:00:52, Map-Id(In): 2,
    flags:
extended, use_count: 0, entry-id: 10, lc_entries: 0

このように表示された。
上のキャプチャ画像の21338が利用されていることがわかる。
キャプチャにあるBE, LEとはビッグエンディアンとリトルエンディアンらしい。
なぜ2つあるかは調べていないので不明。

結論

ICMPのNAPT越えは、ICMPのIdentifierがポート番号の代わりとなる

R2のデフォルトルートを削除してみたところ、Destination unreachableに変化した。
タイプとコードも確認できる。Echo以外も同様にIdentifierが使われているっぽい。

余談

この検証時になぜかpingの応答が重複していた。
eve-ngの問題なのか、コンフィグが間違っていたのか。
なぞ。。。

コメント

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