tcpdump
コマンドラインで動作するパケットキャプチャツールで、ネットワークインタフェースを流れるパケットを1行ずつ表示したり、ファイルへ保存したりする。取り込む条件はlibpcapのフィルタ言語で書いた式で指定し、条件に合わないパケットは、多くのOSでカーネル内のBPFによって捨てられる。
イマシルちゃんの解説
サーバで通信の不調が起きても、画面を持たないサーバでは見た目で操作する解析ツールを使えないことが多いんだ。
そこで活躍するのが、コマンド一つでパケットを取り込めるtcpdumpというツールだよ。
「このIPアドレスとの443番ポートの通信だけ」のように条件を書くと、それに合うパケットだけを拾ってくれるの。
拾ったパケットは画面に1行ずつ表示するほか、ファイルに保存して後から別のツールで詳しく調べることもできるよ。
問題が起きているその場所で実際の通信を手軽に確かめられるのが、とても心強いんだ。
この解説はわかりやすかったですか?
より深い解説
位置付け
tcpdumpは、ネットワークインタフェースで受信・送信したパケットの要約を表示するコマンドラインのツールである。The Tcpdump Groupが、パケット取り込み用ライブラリのlibpcapと一緒に開発している。LinuxやBSD系OS、macOSなどのUnix系OSで広く使われ、サーバやネットワーク機器の調査で最初に手に取られることが多い。
GUIで詳細に解読するWiresharkとは別のプロジェクトだが、どちらもlibpcapの仕組みとpcap形式のファイルを共有している。そのためtcpdumpで保存したファイルをWiresharkで開いて解析できる。オプションやフィルタの公式な説明はtcpdumpのマニュアルとpcap-filterのマニュアルにある。
インタフェースから取り込むには、通常は管理者権限などの特別な権限が必要である。保存済みのファイルを読むだけなら権限は要らない。
主なオプション
| オプション | 意味 |
|---|---|
-i インタフェース | 取り込むインタフェースを指定する。Linuxなどでは any で全インタフェースを対象にできる |
-D | 取り込み可能なインタフェースの一覧を表示する |
-n | IPアドレスやポート番号を名前に変換しない |
-c 数 | 指定した数のパケットを取り込んだら終了する |
-w ファイル | 解読・表示をせずに生のパケットをファイルへ書き出す |
-r ファイル | 保存したファイルから読み込む |
-e | MACアドレスなどデータリンク層のヘッダーも表示する |
-v | 詳しく表示する。-vv、-vvv でさらに詳しくなる |
-X/-A | 中身を16進数とASCII、またはASCIIだけで表示する |
-s バイト数 | 1パケットあたり保存する長さ(スナップレングス)。既定は262,144バイト |
-p | プロミスキャスモードにしない |
-i を省略すると、ループバックを除く稼働中のインタフェースのうち番号の小さいものが選ばれる。複数のインタフェースを持つサーバでは、意図したインタフェースを明示する方が確実である。
-n を付けないと、表示のたびにアドレスからホスト名への逆引きが行われる。DNSが応答しない環境では表示が遅れ、その逆引き自体が取り込み結果に混ざる。障害調査では -n を付けるのが基本である。
コマンドの例
以下のアドレスとファイル名は説明用である。
tcpdump -i eth0 -n host 192.0.2.10 and tcp port 443
tcpdump -i eth0 -n -c 1000 -w web.pcap port 80
tcpdump -n -r web.pcap 'tcp[tcpflags] & tcp-syn != 0'
tcpdump -i eth0 -n -e arp
1行目は、192.0.2.10との間のTCP443番の通信を画面に表示する。2行目は80番ポートの通信を1,000個までファイルに保存する。3行目は保存したファイルから、SYNフラグが立ったパケットだけを表示する。4行目はARPをMACアドレス付きで表示し、データリンク層の問題を調べるときに使う。
フィルタ式に (、)、& のようなシェルの特殊文字を含める場合は、式全体を引用符で囲む。
出力の読み方
TCPのパケットは、おおむね次の形で1行に表示される(独自の例)。
10:15:02.123456 IP 192.0.2.10.50000 > 198.51.100.20.443: Flags [S], seq 1000, win 64240, options [mss 1460], length 0
10:15:02.165321 IP 198.51.100.20.443 > 192.0.2.10.50000: Flags [S.], seq 7000, ack 1001, win 65160, options [mss 1460], length 0
先頭は時刻、次がプロトコル、その後に「送信元アドレス.ポート > 宛先アドレス.ポート」が続く。IPアドレスとポート番号を「.」でつなぐ書き方に注意する。Flags はTCPのコントロールフラグで、S はSYN、F はFIN、R はRST、P はPSHを表す。. はACKを表すので、[S.] はSYNとACKが両方立った応答である。
2行目の ack 1001 は、相手のシーケンス番号1000のSYNを受け取り、次は1001から受け取る準備ができたことを示す。2行の時刻差から、この地点で観測したRTTは約42msと分かる。length はTCPのデータ部分の長さで、ヘッダーは含まない。
フィルタ式の書き方
tcpdumpの条件はキャプチャフィルタとも呼ばれ、pcap-filterの構文で書く。基本は「種類」「方向」「プロトコル」の修飾子と値の組み合わせである。
| 要素 | 主なキーワード | 例 |
|---|---|---|
| 種類 | host、net、port、portrange | net 192.0.2.0/24 |
| 方向 | src、dst | src host 192.0.2.10 |
| プロトコル | ether、ip、ip6、arp、tcp、udp、icmp | udp port 53 |
| 論理演算 | and、or、not、かっこ | tcp port 22 and not src net 192.0.2.0/24 |
ヘッダーの特定のバイトを直接調べることもできる。TCPのコントロールフラグはTCPヘッダーの先頭から13バイト目(0から数える)にある。そのため tcp[13] == 2 はSYNだけが立ったパケットに一致する。SYNのビットの値が2だからである。名前を使って tcp[tcpflags] & tcp-syn != 0 と書けば、SYN/ACKのようにほかのフラグが同時に立っていても一致する。
フィルタ式はtcpdumpの中で解釈されるのではなく、BPF(Berkeley Packet Filter)の命令列に変換されてカーネルへ渡される。カーネル内でのフィルタに対応するOSでは、カーネルが条件に合わないパケットを捨てる。このため不要なパケットをユーザー空間へコピーする負荷を避けられる。-d を付けると変換後の命令列を確認できる。
VLANタグ付きのフレームでは、タグの分だけヘッダーの位置がずれる。タグ付きの通信を取り込むインタフェースでは、vlan キーワードを使ってタグを考慮した式を書く必要がある。
スナップレングスと取りこぼし
スナップレングスを小さくすると、各パケットの先頭部分だけを保存できる。ヘッダーだけ分かれば十分な調査ではファイルを小さくでき、利用者のデータを必要以上に保存せずに済む。ただし短く切ったパケットは上位プロトコルを解読できない部分が残る。
保存量を独自の例で見積もる。1Gbit/sの回線を平均30%の利用率で60秒取り込み、平均のパケット長を800バイトとする。
1秒あたりのビット数 = 1,000,000,000 × 0.3 = 300,000,000ビット
1秒あたりのパケット数 = 300,000,000 ÷ 8 ÷ 800 = 46,875個
60秒のパケット数 = 46,875 × 60 = 2,812,500個
全体を保存 = 300,000,000 ÷ 8 × 60 = 2,250,000,000バイト(約2.25Gバイト)
先頭128バイトだけ保存 = 2,812,500 × 128 = 360,000,000バイト(約360Mバイト)
pcap形式では、これに1パケットあたり16バイトの記録用ヘッダーが加わる。先頭128バイトだけの場合は2,812,500 × 144 = 405,000,000バイトとなる。
取り込みを終えると、tcpdumpは取り込んだ数のほかに「dropped by kernel」の数を表示する。これは処理が追いつかず、カーネルのバッファからあふれて捨てられたパケットの数である。0でなければ、取り込んだファイルに無い通信が実際には存在した可能性がある。-n で名前解決を止める、画面表示ではなく -w でファイルに書く、フィルタを絞る、-B でバッファを大きくする、などで減らせる。
長時間の取り込みとファイルの切り替え
いつ起きるか分からない障害を待ち受けるときは、ディスクを使い切らないようにファイルを切り替える。
| オプション | 働き |
|---|---|
-C サイズ | ファイルが指定サイズ(単位は1,000,000バイト)を超えたら新しいファイルに切り替える |
-G 秒数 | 指定した秒数ごとにファイルを切り替える |
-W 数 | -C と組み合わせると、指定数のファイルを使い回すリングバッファになる |
-Z ユーザー | デバイスを開いた後、指定したユーザーの権限に切り替えて動作する |
例えば -C 100 -W 10 なら、約100Mバイトのファイル10個を順に上書きし、常に直近約1Gバイト分を残せる。障害の発生を確認したら、上書きされる前に該当するファイルを退避する。
Wiresharkとの比較
| 観点 | tcpdump | Wireshark |
|---|---|---|
| 操作 | コマンドライン | GUI(コマンドライン版のTSharkもある) |
| 向いている場面 | サーバ上や遠隔での手早い確認、長時間の記録 | 手元での詳細な解読と統計 |
| 絞り込み | 取り込み時のフィルタ式 | 取り込み時のフィルタに加え、取り込み後の表示フィルタ |
| 解読の深さ | 主要なプロトコルを1行で要約する | 多数のプロトコルをフィールド単位のツリーで表示する |
両者は競合するより補い合う関係である。サーバでtcpdumpを使ってファイルに保存し、手元のWiresharkで開いて詳しく読む流れがよく使われる。
取り込む地点と切り分け
tcpdumpで見えるのは、そのインタフェースに届いたパケットだけである。他の機器同士の通信を見たいなら、スイッチのポートミラーリングやネットワークタップで対象の通信を届ける必要がある。
サーバ自身で取り込む場合は、OS内部の処理の順序にも注意する。例えばLinuxでは、受信したパケットはホストのファイアウォール(netfilter)で破棄される前にtcpdumpへ渡される。「tcpdumpにSYNが表示されたのに応答しない」なら、ファイアウォールでの破棄やアプリケーションの待ち受けを疑う。
| 観測した状態 | 考えられること |
|---|---|
| サーバでSYNが見えない | サーバに届く前の経路や機器で止まっている |
| SYNは見えるが応答を返していない | ホストのファイアウォールで破棄されている、またはSYNの受信処理に問題がある |
| SYNに対してRSTを返している | そのポートで待ち受けるアプリケーションがない |
| ARP要求を出し続けて応答がない | 同じセグメントに相手がいない、またはデータリンク層の接続に問題がある |
| 再送が多い | 経路上のパケット損失や輻輳 |
クライアント側とサーバ側の両方で同時に取り込むと、一方が送ったパケットが他方に届いたかを比べられる。比較の前に両機器の時刻をNTPで合わせておく。
セキュリティと運用の注意
tcpdumpは管理者権限で動かすことが多いので、取り込み開始後は -Z で一般ユーザーの権限に切り替えると、解読処理に脆弱性があった場合の影響を抑えられる。取り込んだファイルには認証情報や個人情報が含まれうるため、取り込む範囲を許可された目的に限り、保存先と保存期間を管理する。
本番機器で長時間動かす場合は、CPUやディスクへの負荷も確かめる。フィルタで対象を絞り、必要ならスナップレングスを小さくする。
午後での問われ方
- tcpdumpなどで取得したパケットの記録を読み、3ウェイハンドシェイクの成否や、RST・再送の有無から障害原因を答えさせる。
- 「サーバで取り込んだのにパケットが見えない」「見えるのに応答しない」状況から、問題のある区間や機器を判断させる。
- 調査用の端末をどこに接続し、スイッチに何を設定すれば必要な通信を取り込めるかを問う。
- 取り込み時刻の差からRTTや処理時間を求めさせる。
- 長時間の取り込みに必要な容量の見積もりや、取り込んだデータの取扱いの注意点を説明させる。