Twitterでとあるツイートを見つけて気になったので。
「pingのポート番号」について。
ICMP(ping)について
結論から言うとICMPにポート番号はない。
ポート番号とはOSI参照モデルにおいてトランスポート層(L4)にて利用されるフィールドであり、
ネットワーク層(L3)のIPで受け取ったパケットを上位のアプリケーションとつなげる役割を担う。
それに対し、ICMPはネットワーク層(L3)で動作するプロトコル。
つまりポート番号は存在しない。
ICMPの役割はL3レベルの通信において、様々なエラーの通知や疎通を確認することであり、
IPの拡張プロトコルとして利用される。
IPヘッダは20バイトあり、その後にICMPが続く。
ICMPヘッダにはタイプ、コード、チェックサムが含まれている。
チェックサムはその名の通り、誤り検出に利用される。
タイプ、コードについてはICMPの種類を特定するのに利用される。
タイプ | コード | 内容 |
---|---|---|
0 Echo Reply | 0 Echo Reply | エコー応答 |
3 Destination Unreachable | 0 Network unreachable | 宛先ネットワークに到達不能 |
1 Host unreachable | 宛先ホストに到達不能 | |
2 Protocol unreachable | プロトコルに到達不能 | |
… | ||
5 Redirect | 0 Redirect for network | リダイレクト |
1 Redirect for host | リダイレクト | |
… | ||
8 Echo Request | 0 Echo Request | エコー要求 |
これら以外にもたくさんあるが、様々なエラーの通知を行うことができる。
今回はこの中でも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 EchoのNAPT越えは、ICMPのIdentifierがポート番号の代わりとなる。
【追記】詳細はRFC5508に記載があるため読んでみると良さそう(コメントいただきました)
余談
この検証時になぜかpingの応答が重複していた。
eve-ngの問題なのか、コンフィグが間違っていたのか。
なぞ。。。