ターゲットマシンとの間にあるルーターのIPアドレスを取得する

ターゲットマシンとの間にあるルーターのIPアドレスを取得する


今回はネットワークとプログラミング両方の学習に役立つ簡単なtracerouteを実装します。
ネットワークプログラミングのいい勉強になりますし、そこそこ格好いいのでいろいろと意味があると思います。

このツールを利用すると通信先マシンへの経路上にあるマシンのIPアドレスなどの情報を取得することができます。

原理をまとめそれを実装してパケットがどのようにネットワークを移動するのか見ていきます。



そもそもどのように対象のマシンへパケットが送られるか

僕も普段何気なくインターネットを利用していますが、
中を覗いてみるとそこそこ面倒なことをやっているようです。

インターネットのどこかのマシンと通信する際は直接そのマシンとやり取りしているわけではなく、ルーターを経由してパケットを送りあっています。

通信先との間にルーターがあるわけですが何台あるかはわかりません。
例えば5台あるとすれば5回ルーターを経由して対象のマシンへとパケットが送られます

time to live

しかしIPパケットにはtime to live(IPv6ではhop limit)という寿命のようなものがあります。
このtime to liveというのは簡単に言うとルーターを何台超えることができるかを定めた値です。

たとえば対象マシンとの間にルーターが5台あり、time to liveが3だとするとこのパケットは対象のマシンへと到達する前に破棄されてしまいます。
それはtime to liveが3であるため3回しかルーターを超えることができないからです。
ルーター(ルートのホスト)を通るたびにtime to liveはデクリメントされていきます。
そしてゼロになるとTimeExceededを知らせるICMPパケットが送信者に向けて返却されます。

ルートスキャンというものはこの原理を利用しています。

原理

time to liveがゼロになるとTime Exceededを知らせるICMPパケットが送信者に向けて返却されると書きました。

このICMPパケットにはICMPパケットを発行したルーターのIPアドレスが格納されています。
とういことはルート上にルーターが5台あるとして、
time to liveを1にすれば、自分のマシンの、一つ先のマシンの情報が取得できるということです。

一つ先のマシンからICMPパケットを受信したら、次はtime to liveを2に設定して、通信したい相手へとパケットを送信します。
そうすると2つ先のマシンがICMPパケットを返却してきます。(time to liveが2だから)
そして2つ先のマシンの情報も取得できます。

これを最終到達地点のマシンへパケットが届くまで、time to liveをインクリメントして繰り返すのです。

こうすることで、ルート上のマシンの情報が取得できるということです。

実装


冷静になって実装します。

まずはソケットを作成する部分です。
今回はicmpパケットを送受信します。
特にこれといったことはやっていません。
ソケットの作成に成功したらディスクリプタを、失敗したら-1を返却します。


次は早速送受信です。

ipヘッダーとicmpヘッダーに諸々値を設定します。
今回はicmp echo requestパケットを送信するためicmp_typeにICMP_ECHOを設定します。

Time to liveが0になれば時間超過を知らせるtime exceededパケットが返却され、
ターゲットにパケットが到達すればecho replyが返却されます。

その解析をanalyze関数にお任せします。
echo replyが返却された場合は1、
time exceededが返却された場合0、
それ以外は一応2を返却します。

analyze関数から「1」が返却された場合は最終目標に到達したわけですから、
パケット送信ループを抜けます。
「0」の場合はTime to liveをインクリメントして送信処理を続行します。

ソースコード


最終的にこのようなプログラムになります。