PCを使ううえでインターネットをはじめとするネットワーク機能は欠かせません。ネットワーク上ではさまざまなプロトコルやサービスに応じたパケットやフレームを機器間でやりとりしています。そこで今回はそんなネットワークのトラフィックの中身を見るために定番の、tcpdumpとWiresharkの基本的な使い方について紹介します。
Ubuntuなら常にインストールされているtcpdump
「tcpdump」はlibpcapを利用したネットワークトラフィックをキャプチャ・表示するツールです。Ubuntuのstandardタスクに属しているため、普通のUbuntuやそのフレーバーであれば、常にインストールされているツールでもあります。
とりあえず実際に実行してみましょう。
おそらくいろんなホストとの通信メッセージが表示されるはずです。「-c 10」は10パケット受信したら終了と言うオプションで、これがないとCtrl-Cを入力するまで延々とパケット情報を表示します。
出力の先頭フィールドは時刻です。その後ろについては、パケット種別によってフォーマットが異なります。たとえばARPパケットなら、問い合わせ内容と問い合わせ元のアドレスを表示します。
上記だと192.168.10.10から192.168.10.3のMACアドレスを問い合わせ、その結果が返ってきていることがわかります。
IPパケットであれば「送信元 > 送信先」のあとに、その内容を解析して概要を表示しています。
上記は192.168.10.4と192.168.10.10の間でssh通信が行われているときの様子です。
フィルタリング機能
tcpdumpは特にオプションを指定していない場合、そのホストが接続されているネットワーク上のパケットを表示します。しかしながら、その量は膨大であるため、必要な情報はすぐに流れてしまいます。そのため、tcpdumpには強力なパケットフィルタリング機能が存在します。
「-i」オプションはキャプチャするネットワークインターフェースを指定します。
「-P」オプションは受信パケットか送信パケットかを制約します。inなら受信パケットのみ、outなら送信パケットのみ、inoutなら送受信両方です。
なおこの「-P」オプションは14.04までのtcpdumpでのみ有効です。14.10で採用している4.6.2以降のtcpdumpは「-Q」オプションに名前が変わっているので注意してください。
オプションでは基本的なルールしか設定できませんが、コマンドの末尾にpcap準拠のフィルタリングルールを記載できます。パケットをフィルタする場合はこちらを使うほうが多いでしょう。
特定のホストに関連するパケットだけを表示したい場合はhostフィルタを使用します。また、各フィルタはandやor、notなどで連結可能です。
特定のポートの通信だけを表示する場合は、portフィルタを使用します。ポート番号でも指定できますし、/etc/servicesに列挙されていれば名前を使うこともできます。さらに各フィルタは「dst」や「src」を追加すると、宛先、送信元それぞれのポートに限定できますし、「tcp」や「udp」などプロトコル指定も可能です。
その他にもいろいろなルールを指定できます。詳しいことはpcap-filterのマニュアルを参照してください。
出力のカスタマイズ
tcpdumpは特に指定しなければ、各パケットの概要を1行で表示します。ただし、サポートしていないプロトコルについては送信元と宛先、データサイズぐらいしか表示されません[1]。
しかし実際にtcpdumpを使用する場合は、サポートしていないプロトコルの、具体的なパケットの内容を表示したいこともあるでしょう。そこでtcpdumpには便利な出力オプションがいくつも存在します。
「-x」オプションを使うと、データの内容を16進表記で出力してくれます。バイナリデータのやり取りを行う通信を確認したい時に便利でしょう。「-A」オプションならASCII表示にしてくれますので、HTMLなどのテキストデータを確認できます。「-X」だとhdコマンドのように16進とASCIIをならべて表示してくれます。
下記は80番ポートの通信を監視しつつ、Webブラウザーでhttp://gihyo.jp/にアクセスした時の抜粋です。3ウェイ・ハンドシェイクのあとに、HTTP/1.1のGETメソッドの通信が行われていることがわかります[2]。
他にも「-n」オプションを付けるとホスト名やプロトコルをそれぞれIPアドレス、ポート番号のまま表示します。「-N」オプションはドメイン名のうちホスト名部分のみを表示します。
「-e」オプションを付けると、Ethernetフレームの情報などデータリンク層のヘッダーも一緒に表示します。16進ダンプしたい場合は「-x」や「-X」をそれぞれ「-xx」、「-XX」に変更してください。
ファイルへの保存とファイルからの再生
tcpdumpはネットワークトラフィックの様子をほぼリアルタイムで表示しますが、デバッグ目的のためにあとから見返したいこともあるでしょう。また、キャプチャ時はフィルタリングルールを設けずに、関連しそうなパケットをとりあえず全部取得し、その後tcpdumpで仕分けしたい場合もあるはずです。
そんなときに便利なのが指定したファイルに保存する「-w」オプションです。
tcpdumpはlibpcap形式のバイナリデータとしてパケットの内容を保存します。「-U」オプションとセットで利用すると、パケットを受信したら即座にファイルに保存します。一度保存すれば「-r」オプションで当時のトラフィックの様子を再度確認できます。
上記の「port 80」のように、通常と同様のフィルタリングルールを利用可能です。
ちなみにUbuntuの場合、AppArmorによって拡張子が「.pcap」のファイルのみtcpdumpの「-r」オプションに渡すことが可能になっています[3]。「yano.log」や「yano.dat」では「Permission denied」になるので注意してください。
pcapファイルが大きくなりすぎないように、「-C」オプションを使って上限サイズを設けて、ローテーションさせることも可能です。「-G」オプションを使うと、指定した時間ごとにローテーションします。どちらのオプションも「-W」オプションでローテーションの数を制限できます。「-z」オプションを使うと、ローテーションのタイミングで任意のスクリプトやコマンドを実行できますので、継続的なログを取得する際に利用すると良いでしょう。
tcpdumpは個々のパケットで65535バイトを超えるデータは切り捨てています。このサイズは「-s」オプションで変更できますが「-s 0」とすることで、パケットすべてを保存できます。pcapファイルに保存する場合はこのオプションも併せて付けておけば、あとからの追跡調査の場合に取りこぼしがなくなります。
GUIによるアナライザーWireshark
「Wireshark
」はマルチプラットフォームに対応した、GUI付きのネットワークプロトコルアナライザーです。Linux版のWiresharkはtcpdumpと同様にバックエンドにlibpcapを利用してネットワークトラフィックをキャプチャします。洗練されたわかりやすいUIを備えているので、キャプチャしたパケットの解析はtcpdumpよりも使いやすいです。Ubuntuでもwiresharkパッケージをインストールすれば導入できます。
ところでネットワークトラフィックをキャプチャするには管理者権限が必要です。tcpdumpの場合はsudo付きで起動しましたが、wiresharkの場合は以下の3つから選べます。
- pkexecを使って管理者権限で起動する
- wiresharkグループに属してdumpcapを利用する
- tcpdumpやdumpcapで出力したpcapファイルを読み込む
1.はWiresharkを管理者権限で起動する方法です。polkitの設定が必要なうえ、GUIアプリを管理者権限で起動することに抵抗があるかもしれません。
2.はインストール時の質問にYesと答えたときに行われる設定です。インストール時にNoと答えた場合でも、以下のコマンドで再設定できます。
wiresharkグループが作成されますので、次のコマンドでユーザーをそのグループに追加します。
追加後は一度ログインしなおしてください。さらにdumpcapコマンドもインストールしておきます。
これで一般ユーザーで起動したWiresharkでも、ネットワークトラフィックをキャプチャできるようになっているはずです。この方法だと管理者権限は必要ありませんが、wiresharkグループに属しているユーザーであれば誰でもキャプチャできるようになる点は注意が必要です。
3.はWiresharkを解析のみに利用し、キャプチャするコマンドは別途用意する方法です。libpcap形式であればtcpdumpを、pcapng形式であればdumpcapコマンドを利用します。この方法はWiresharkがインストールされていないようなマシンでキャプチャしたデータも利用できるため、普段はこの方法でも充分でしょう。
WiresharkのCUI版TShark
WiresharkのCUI版が「TShark」です。Debianパッケージの場合はwiresharkパッケージとは分離されて、tsharkパッケージとして提供されてます。
tsharkのキャプチャ機能はtcpdumpのそれと大した違いはありません。tsharkで便利なのは、CUIでもWiresharkと同等のディスプレイフィルタ機能やパケットの詳細表示機能が使えると言うことでしょう。
たとえばtsharkでpcapファイルを読み込むと次のように表示されます。
このうち4番目のフレームの詳細を表示するには次のようにframe.numberでフィルタリングします。
パケットデータ部分を表示する場合は、「-x」オプションを使用します。
他にもtsharkであれば「-z」オプションを使って、パケットの内容に応じた統計情報を表示することも可能です。
プログラミング言語でも
今回紹介したtcpdump/Wireshark/TSharkはいずれもLinux版はlibpcapのフロントエンドです。もし特定の条件のパケットを受信したときにもっと柔軟に処理を行いたい場合は、libpcapを使ったプログラムを作成すると言う方法もあります。
libpcapを直接使うにはC言語を使う必要がありますが、libpcapには各プログラミング言語のバインディングが存在します。たとえばPythonならPyCapなどがありますし、Goであればgopacketにpcapというパッケージが存在するようです。よって、好みの言語を使って開発することはそれほど難しくはないでしょう。