テックブログ

技術ネタ

コマンドライン上でリアルタイムにプロトコル内容を確認できる tshark のススメ

はじめまして。新人の H.M.です。

サーバ上の通信を確認するのに、tcpdump はよく使われていると思います。プロトコルが絡んでちょっと詳しく調べたいというときには、tcpdump で保存したパケットキャプチャのデータを PC に持ってきて Wireshark で確認しているという方もそれなりにいらっしゃるでしょう。

Linux でもデスクトップがあれば Wireshark で GUI を使ってキャプチャと分析ができますが、デスクトップを入れていないサーバではいちいちキャプチャをダンプして PC に持ってくる作業が面倒ですよね。

実は Linux 向けの Wireshark には tshark というコマンドラインツールも付いています。tshark は tcpdump のようにリアルタイムにパケットをキャプチャをするだけでなく、プロトコルを解釈した内容も表示することができます。更に、Wireshark のフィルタも使用することができ、通信量が多い本番環境でも確認したい通信内容をアプリケーション層レベルで絞り込んで確認することができます。

インストールと動作確認、キャプチャフィルタ

tshark は RedHat系 OS であれば wireshark パッケージに含まれていますので、下記のようにインストールします。

 # dnf install wireshark

パケットのキャプチャ時は、tcpdump と同様にインタフェースを -i オプションで指定します。当然ですがキャプチャをするには root 権限が必要です。-i オプションは複数指定でき、フォワーディングしている場合などでも確認に便利です。

 # tshark -i eth0

これで tcpdump のようにキャプチャしたパケットが流れているのを確認できたと思います。

tshark のキャプチャ時のデフォルトのフィルタはキャプチャフィルタと呼ばれています。tshark はオプション指定以外の文字列がデフォルトのフィルタコマンドになります。オプションとデフォルトフィルタの順序は任意なのですが、入り乱れると混乱しやすいので、デフォルトのフィルタは常にコマンドラインの最後に記述することをお勧めします。

Wireshark / tshark は tcpdump と同じく pcap ライブラリでパケットのキャプチャをしており、キャプチャフィルタは pcap ライブラリと同じ構文(つまり tcpdump のフィルタと同じ構文)になります。

例)HTTP パケットを確認する

例)SSH 以外の TCP パケットを確認する

「(」,「)」はシェルが解釈してしまうので、キャプチャフィルタに指定する場合にはシングルクォートもしくはダブルクォートで囲む必要があります。

tshark ではキャプチャしたパケットのプロトコルを解釈して、その内容も出力してくれます。例えば HTTP の場合、下記のような出力が確認できます。

ファイルへの保存と読み込み、リードフィルタ

キャプチャしたパケットデータを -w オプションでファイルに保存できます。Ctrl-C キー等で tshark を終了させるまでの間の、キャプチャフィルタ(下記の例では「port 80」)適用後のパケットがファイルに保存されます。

-w オプションと共に -P オプションを付けると、キャプチャして保存するパケットの状況が画面にも表示されます。

キャプチャを保存したファイルは -r オプションで読み込ませることで、後から tshark で通信内容を確認できます。もちろん Wireshark があれば、そちらに読み込ませて解析させることもできます。

上記の例では、キャプチャ時に保存されたパケット情報の全てが表示されます。

キャプチャしたデータをファイルから読み込む場合(つまり -r オプションを指定した場合)にもフィルタを指定できます。読み込み時のデフォルトのフィルタはリードフィルタと呼ばれ、Wireshark のフィルタ構文を使用します。キャプチャフィルタと同様、リードフィルタがデフォルトフィルタの場合もコマンドラインの最後に記述するのが無難です。

ここで、リードフィルタに http を指定してみます。

すると、http プロトコルの内容に絞って結果が表示されます。

下記のようにすれば、HTTP リクエストの Host ヘッダが特定のドメイン(ここでは「www.xxx.co.jp」)であるトラフィックについて絞り込めます。

更に、URI のパス(ここでは「/category」から始まる場合)のマッチでフィルタすることができます。

なお、上記ではチルダ(~)をシェルが解釈してしまうため、リードフィルタ全体をシングルクォートでまとめています。

もう一つの例として、メール送信を確認してみましょう。tshark でポート 25 の通信をキャプチャして保存します。

別のターミナルでメールを送信してみます。下記の例では s-nail を使ってメール送信をしています。(サーバからの送信に OP25B 制限はなく、認証も不要な前提です。送信先の SMTP サーバは調べてください。SPF なども適宜設定しておいてくださいね)。

キャプチャしたデータの読み込みで、リードフィルタに smtp プロトコルを指定してみます。

下記のように、smtp プロトコルのやり取りを確認することができます。

アプリケーションレイヤのプロトコル情報

さて、せっかくここまでできているのであれば、アプリケーションレイヤの情報を確認したいですよね。tshark では -O オプションを付けることでアプリケーションレイヤのプロトコル情報が確認できます。

先に保存した HTTP のキャプチャ結果を見てみましょう。リードフィルタで http に絞り込んで、-O オプションで http プロトコルを指定します。

下記のような結果が返ってきます。

HTTP のリクエストとレスポンスのプロトコル情報、HTTPヘッダに関する情報が確認できました。

上記の例では Webページがリダイレクトしているためレスポンスボディが空になっています。もし HTTP のボディ要素があれば、ダンプ形式でその内容が表示されます。なお、HTTP のボディ要素が全てダンプされるため、一般的な Web アクセスですと出力が大量になるのでご注意ください。

キャプチャ時のアプリケーションレイヤ表示とディスプレーフィルタ

実は -O オプションはキャプチャ時にも使用できます。キャプチャ時のデフォルトフィルタはキャプチャフィルタであることに注意してください。

こうすることで、キャプチャ時でもアプリケーションレイヤの情報を確認することができます。ただ、実行してみればわかるとおり、アプリケーションレイヤだけでなく、パケットレベルの情報も出てきて、結構うざいです。

実は、画面出力に対して Wireshark の構文でフィルタできるディスプレーフィルタというオプションがあり、これはキャプチャ時でも使用できます。ディスプレーフィルタは必ず -Y オプションで指定します。

下記の場合、キャプチャフィルタで「host yyy.yyy.yyy.yyy」を指定して通信相手の IPアドレスをフィルタし、-Y によるディスプレーフィルタで HTTP プロトコルに表示を制限して、-O で HTTP のプロトコル情報を表示させます。

「-Y http」を指定することで、画面には HTTP のアプリケーションレイヤのプロトコル情報だけが表示されます。

ディスプレーフィルタで Wireshark の構文による様々なフィルタの指定をおこなうことができますが、あくまで -Y オプションのパラメータなので、必要に応じて文字列をクォートすることを忘れないでください。下記は、ディスプレーフィルタで http の Host ヘッダが「xxx.xxx.co.jp」の場合に絞り込む例です。

ここまでで、tshark を使って Wireshark のフィルタ機能で表示させるトラフィックを絞り込んで、リアルタイムにアプリケーション通信の確認をおこなうことができることがご理解いただけると思います。

HTTPS通信の復号と、TCP のトレース

Webサーバで暗号化通信をしている場合、鍵の情報があればアプリケーション通信の内容を確認することができます。昔は RSA鍵交換が普通だったのでサーバ鍵を使えば共通鍵を取得して復号できたのですが、現在は一時鍵による鍵交換が主流になってきているため、気軽には HTTPS の通信を復号できません。自身で通信した時の共通鍵(Pre-Master-Secret)をファイルに保存しておくことで、その通信に限って復号できます。

パケットのキャプチャ方法は今までと同じです。HTTPS 通信なので port 443 の通信をキャプチャします。

Webサーバと通信する際に、クライアント側で共通鍵をファイルに保存します。共通鍵の保存は OpenSSL ライブラリなどで対応しており、保存先ファイル名を SSLKEYLOGFILE という環境変数で指定します。下記は curl を使った例です。

最近の curl は HTTP/2 や TLS 1.3 にも対応していますが、tshark はバージョンによってはサポートしていなかったり、HTTP/2 は HTTP/1.1 とはだいぶ様相が異なるなどのため、話の都合上、ここでは HTTP/1.1、TLS 1.2 以下に制限しています。

通信が終わったら tshark のキャプチャを終了させます。

curl で保存した共通鍵のファイルを「-o “tls.keylog_file:/tmp/sslkeylog”」で指定したうえで、保存したキャプチャファイルを tshark に読み込ませます。-O オプションで http のプロトコル情報を出力し、リードフィルタで http だけに出力を制限します。

下記のように、復号したアプリケーションレイヤの情報が取得できます。

なお、共通鍵の読み込みはキャプチャ時にも利用することができるので、同一サーバで curl などで SSLKEYLOGFILE の共通鍵ファイルを共有できるのであれば、リアルタイムに復号することができます。

アプリケーションレイヤのトラフィックのトレース

-O オプションでは HTTP ボディ情報が HEX ダンプとテキストが並ぶかたちで表示されます。これを、「-z ‘follow,tls,ascii,0’」に置き換えることで Wireshark の TCP トレースのように通信内容を表示させることもできます。

下記のような結果が確認できます。

なお、-z オプションをキャプチャ時に指定することも可能ですが、キャプチャを終了してからでないとトレース結果が出力されないため、リアルタイムで確認することはできません。

特定のフィールドを出力する

-O オプションによるアプリケーションレイヤの情報は個別の通信を確認するためには便利ですが、本番などで常に通信が流れ続けている場合は大量に出力があるので不向きです。そのような場合には、プロトコル上の特定のフィールドだけを出力できると確認しやすくなります。

tshark では「-T fields」に続けて -e オプションを指定することで、プロトコル特有のフィールドも含めて特定の情報のみを出力させることができます。「-T fields」と -e オプションはキャプチャ時にも利用できます。

例えば、フレーム番号、IPアドレス、送信元ポート、送信先ポート、HTTPプロトコル、HTTP Host ヘッダ、HTTP リクエスト URL (パス) を表示させる場合、下記のようになります( -Y オプションで http パケットに絞り込んでいます)。

上記によって、リアルタイムのキャプチャで下記のような出力が得られます。

更に「-e http.cookie」を追加すれば Cookie を確認することもできます。また確認した Cookie を「-Y ‘http.cookie matches “<Cookieの文字列>”‘」でディスプレーフィルターに設定すれば、その Cookie のユーザだけを追いかけることも可能になります。

まとめ

今回は、リアルタイムにパケットキャプチャしながらアプリケーションレイヤの情報も表示やフィルタ条件で使用できる tshark をご紹介しました。取りつきにくさのあるコマンドなので実例でわかりやすく解説したつもりですがいかがでしたでしょうか。更に詳しく知りたければ「man tshark」をご参照ください。

様々なアプリケーションがネットワークでつながる中、挙動のわからないアプリケーション動作をネットワーク側から確認することで解決に導けることも多々あると思いますので、皆様のお役に立てば何よりです。

それでは楽しいインターネットライフを!

この記事をシェアする

  • facebook
  • twitter
  • hatena
  • line
URLとタイトルをコピーする

実績数30,000件!
サーバーやネットワークなど
ITインフラのことならネットアシストへ、
お気軽にご相談ください