トップ > スキル : ネットワーク > プロトコル(ICMP)

ネットワーク

ICMPの実装

ネットワークにトラブルが生じたときに使うのがネットワーク・コマンドです。定番となるpingコマンドは、ICMPを利用してネットワークのつながりを確認できるものです。ICMPの利用にはpingコマンドのように意識して使う場合と、ユーザがまったく見えないところで活躍している場合があります。一般にICMPを使う場面を列挙すると、WindowsのICMP処理、pingコマンド、tracerouteコマンド、ポートスキャンがあります。

WindowsマシンでのICMP処理

WindowsにおけるTCP/IPがICMPを処理する場面を紹介すると、まず通信相手との間でIPパケットを分割せずにやり取りできるMTUサイズを探す仕組みである「経路MTU探索」があります。MTUサイズとは、パソコンが1度に送出できるデータの最大サイズの値です。これは基本的に回線の種類で決まります。通常イーサネットなら最大1500バイト、ADSL(PPPoE)なら最大1492バイトとなっています。

経路MTU探索の仕組みを見ていくことにします。まずWindowsが通信相手にIPパケットを送るときに、IPヘッダー内のDFフラグ(分割禁止)を有効にし、パケットを送信します。例えば、Windowsパソコンが1200バイトのパケットを送り出したとします。通信経路の途中でMTUサイズが1000バイトの部分では、パケットが1200バイトなので、そのまま通すことはできません。ルータはパケットを分割して通そうとしますが、DFフラグがオンになっているので分割できません。そこで、ルータはパケットを破棄すると同時に「分割したいけど分割できない」というメッセージをICMPを使って送信元のパソコンに通知します。このときのICMPパケットのタイプは「3」でコードは「4」です。これは、分割が必要だが、分割できないのであて先まで届けられないことを意味します。また、多くのルータはこのとき、ICMPパケットのオプション・データ部分に。分解せずに通せるMTUサイズを埋め込んで送ります(この例では、1000バイトとなります)。パソコンは、このICMPパケットを受け取ると、分割せずに送れるパケットのサイズが分かるので、一時的にMTUサイズを変更して、再度パケットを送ることでIP通信を続けることができます。

WindowsのICMP処理の2つ目は、リダイレクトです。これはルータなどが送信元のパソコンに対して経路変更を指示する仕組みです。一般的にLAN内に複数のルータが存在するときに使われます。

パソコンは、パケットを送る際に所有しているルーティング・テーブルを見て転送先を決めます。違うサブネットに送るのであれば、デフォルト・ゲートウェイとなるルータにパケットを送ります。ルータは受け取ったパケットの中身を見て、他のルータに送ったほうが近いと判断すると、このことを送信元のパソコンにICMPを通知します。パソコンはそれを受け取り、自分のルーティング・テーブルを書き換え、あて先IPアドレスとの通信をしばらくの間指示されたルータ経由で行います。このときのICMPパケットのタイプは「5」でコードが「1」となり、オプション・データ部分には送信元がパケットを送るべきルータのIPアドレスが埋め込まれます。

3つ目としてフロー制御があります。ルータに一度に多くのパケットが届くと、処理しきれなくなりパケットを破棄してしまう場合があります。このようなとき、ルータが送信元のパソコンに対して、パケットの送信を抑えてもらうように送るのがICMP送信元制御メッセージです。

ルータは、多くのパケットが届いた場合処理できないパケットは一時的にバッファに貯めておきます。しかし、このバッファまでもあふれるようであれば、ICMPを使って送信元にメッセージを送ります。そのメッセージを受け取った送信元パソコンは、自動的にIPパケットを送り出す間隔を広げて、通信速度を落とします。こうすれば、ルータが処理できないパケットを捨て続けることを防ぐことができます。このときのICMPパケット内のタイプは「4」でコードは「0」です。

pingコマンド

pingコマンドは、指定したマシンとネットワーク上で繋がっているかどうかを確認したり、パケットが往復するのにどれくらいの時間がかかるかを調べるためのコマンドです。pingでは2つのICMPメッセージを使っています。

では、pingコマンドを実行したときの手順を見ていきます。pingを実行すると最初にあて先のマシンに向けてICMPの「エコー要求」メッセージを送ります。エコー要求メッセージのICMPタイプは「8」でコードは「0」となり、その他に「識別子」と「シーケンス番号」の値が追加されます。識別子は、pingコマンドを実行している間、送り出すすべてのパケットに同じ値をいれます。シーケンス番号は、パケットを送り出すたびに数を増やしていきます。また、エコー要求ICMPでは、オプション・データ部分にダミー・データを入れて、やり取りされるパケットサイズを調整しています。

エコー要求が相手となるマシンに届くと、これに応えて「エコー応答」メッセージが送信元に向けて送り出されます。このときのICMPパケットのタイプは「0」でコードも「0」です。ICMPエコー応答とICMPエコー要求の違いは、送信元とあて先IPアドレスが入れ替わっていることと、タイプの値だけです。要するに、送信元となるパソコンから見ると、自分が送ったICMPパケットがあて先となるマシンからそのまま送り返されたことになります。このことで、送信元となるパソコンは、エコー応答を受け取ることであて先のマシンが稼動していることが確認できます。ただし、送信元パソコンは、もし受け取ったエコー応答にタイプとコードしか書かれていないと、本当に自分が送ったエコー要求に対する応答なのか判断できません。ここで先に述べた識別子とシーケンス番号が意味を持ってきます。つまり、この2つの値を受け取ったエコー応答の値と比較すれば、送信元が送ったエコー要求に対するものであるか判断できます。pingコマンドを実行した結果として、あて先のIPアドレスとデータのサイズ、往復にかかった時間などが画面上で確認できます。もちろん、お互いに通信ができたことを前提とします。

エコー応答が必ず返ってくるとは限りません。pingコマンドで相手との接続を確認できない原因が3つあります。1つは、あて先となるマシンが存在しない場合、それとパケットのやり取りに時間がかかってしまいタイムアウトとなる場合、そしてあて先マシンがpingに応えない場合です。タイムアウトになるのであれば、待ち時間を延ばして正しい結果を表示できますが、あて先のマシンの存在とpingに応えない場合、pingだけでは接続を確認することはできないことを覚えておきましょう。

tracerouteコマンド

tracerouteコマンドは、目的のホスト名やIPアドレスを指定し実行すると、途中の経路上にあるすべてのルータの名前やIPアドレスを調べてくれるコマンドです。では、この中でどのようにICMPが使われているのかを手順を追って見ていきます。

Windowsでtracerouteコマンドを実行すると、最初パソコンは目的のマシンに向けてIPパケットを送出します。ここで送り出すパケットはpingコマンドと同じICMPエコー要求と同じですが、1つだけ異なる点があります。それは、IPヘッダーのTTL(生存時間)の値を最初は「1」を設定しているという点です。TTLは、パケットがルータを経由するたびに値を1つずつ減らされます。そして、TTLが0になったとき、ルータはパケットを破棄する決まりになっています。TTLの意味は生存時間ですが、時間というよりルータを通過できる数と考えたほうが分かりやすい。

パソコンが送出したパケットがルータを通過するとします。このとき、ICMPエコー要求パケットのTTLが「1」だと、ルータが処理することでTTLが「0」になり、そのルータで破棄されます。と同時に、送信元に対してICMPを使ってエラー通知をします。このときのタイプは「11」でコードは「0」のICMP時間超過メッセージとなります。また、ICMPのオプション・データ部分には、元のエコー要求パケットのうちIPヘッダーとICMPデータ部分の先頭8バイト分のデータを入れます。

1つめのパケットに対するICMP時間超過メッセージを受け取ったパソコンは、次にTTLを1つ増やしTTL=2のICMPエコー要求パケットを送出します。すると、今度は1つめのルータを通過するとTTLを1にし、2つめのルータに届きます。2つめのルータは先ほどと同じようにTTLを0にしてパケットを破棄し、同様にICMP時間超過メッセージを送信元に送ります。以後、TTLを1つずつ増やして同じ作業を繰り返すことで、いつかはあて先となる目的のマシンに到達します。このとき、あて先のマシンだけは、途中のルータと異なりICMP時間超過メッセージは返しません。その代わりに、ICMPエコー要求に対する、エコー応答を送信元のパソコンに返します。つまり、ここでpingコマンドを実行していることと同じになります。このように、経路上にあるルータから戻ってきたエラーをリストアップして、あて先までの経路を構成するルータの情報を知りえるということになります。

ポートスキャン

ポートスキャンとは、サーバに不要なポートが空いていないかをチェックするために行う操作です。大きく分けると「TCPのポートスキャン」と「UDPのポートスキャン」があります。ICMPが関係するのはUDPの方ですので、ここではUDPのポートスキャンを見ていきます。

UDPにはTCPのような接続手順がないので、開いているポートを調べるにはICMPを使った工夫をしています。ICMPの仕様には、UDPパケットがサーバの存在しないポート宛に届いた場合、サーバはICMPメッセージ「あて先到達不能」メッセージを返すことになっています。そこで、調べたいサーバに向かって適当にポート番号を指定してUDPパケットを送ると、あて先ポートが開いていない場合は、サーバがICMPポート到達不能メッセージを返すことになります。この返されたICMPパケットのオプション・データ部分には、送信元のパソコンが送り出したUDPパケットのIPヘッダーとUDPヘッダーの先頭部分が入っています。これをみて、送信元はどのUDPパケットに対するエラー通知なのかを識別し、そのポート番号がサーバで使われていないことを判断します。

しかし、この方法で分かるのはICMPポート到達不能メッセージが返ってくるとそのポートは閉じていることは分かりますが、そのメッセージが返ってこないことで「ポートが開いている」とはいえません。これはTCPのポートスキャンと大きく異なる点でもあります。

ポートスキャンは、管理者がサーバに不要なポートが開いていないかを確認する目的で使用されるが、クラッカが不正アクセスの事前調査として使用することもあるので、使うときは細心の注意が必要です。

【ICMP:ICMPの実装】