tcpdump 入門 - パケットキャプチャで通信を可視化する

tcpdump 入門 - パケットキャプチャで通信を可視化する

この記事で解決できること

  • tcpdumpパケットを取り始める最短手順 が分かる
  • BPF フィルタで 見たい通信だけに絞り込む 方法が身につく
  • pcap 保存 → Wireshark で読む 連携の型が分かる
  • 「接続できない」「応答が遅い」を パケットレベルで切り分け できる

結論(実務の型)

  • まず sudo tcpdump -i any -nn で生きている通信を眺める
  • 騒がしいときは host / port フィルタで対象を絞る
  • 後で解析するなら -w cap.pcap で保存し Wireshark へ
  • 原則 -nn を付ける(名前解決の待ちで固まらない)

前提(対象環境)

  • OS:Ubuntu / 一般的な Linux
  • tcpdump はパケットキャプチャに root 権限(CAP_NET_RAW)が必要 → sudo 前提
  • 未インストールなら sudo apt install tcpdump

tcpdump とは何か?

結論: tcpdump は CLI のパケットキャプチャツール。NIC を流れる生のパケットを取得・表示し、通信の有無や中身を直接確認できる。

tcpdump は、ネットワークインターフェイス(NIC)を通過するパケットをそのまま取得して表示する CLI ツール。Web の応答が返らない、TCP が確立しない、といった事象を「サーバまでパケットが届いているか」「応答が返っているか」という事実ベースで切り分けられる。

GUI の Wireshark と内部のキャプチャ基盤(libpcap / BPF)は共通で、tcpdump はその CLI 版にあたる。サーバ上で SSH 越しに即実行できるのが強み。

パケットキャプチャは通信内容(場合によっては認証情報)を観測する行為。自分が管理する環境・許可された環境でのみ実行すること。

最短でキャプチャを始めるには?

結論: sudo tcpdump -i any -nn が出発点。インターフェイス指定 -i、名前解決抑止 -nn、件数制限 -c の3つを押さえれば十分動かせる。

まず流れている通信を眺める

$ sudo tcpdump -i any -nn
  • -i any:すべてのインターフェイスを対象(特定なら -i eth0
  • -nn:ホスト名もポート名も解決しない(DNS 逆引き待ちで固まらない / 数値のまま速く読める)

取得可能なインターフェイスを確認する

どの IF を指定すべきか分からないときは一覧を出す。

$ tcpdump -D
1.eth0 [Up, Running, Connected]
2.any (Pseudo-device that captures on all interfaces) [Up, Running]
3.lo [Up, Running, Loopback]

件数を区切って止める

tcpdump は止めるまで流れ続ける。-c で件数を区切ると扱いやすい。

$ sudo tcpdump -i any -nn -c 20

手動で止めるときは Ctrl + C。終了時に「received / dropped by kernel」の統計が表示される。dropped が多い場合は取りこぼしが発生している。

出力の1行をどう読むのか?

結論: 各行は「時刻 送信元 > 宛先 フラグ・シーケンス・長さ」の順。> の向きと TCP フラグ(S/F/P/R/.)で通信の流れと状態を読む。

典型的な TCP の1行は次の形。

10:11:12.345678 IP 192.168.1.10.54322 > 93.184.216.34.443: Flags [S], seq 123456, win 64240, length 0
要素 意味
10:11:12.345678 タイムスタンプ
192.168.1.10.54322 送信元 IP とポート(末尾がポート)
> 通信方向(左 → 右)
93.184.216.34.443 宛先 IP とポート(443 = HTTPS)
Flags [S] TCP フラグ(後述)
length 0 ペイロード長

TCP フラグの読み方

表記 フラグ 意味
S SYN 接続開始要求
S. SYN/ACK 接続要求への応答
. ACK 確認応答のみ
P PSH データ送出(push)
F FIN 接続終了
R RST 接続の強制リセット

3ウェイハンドシェイクが成立していれば [S][S.][.] が並ぶ。[S] を送って [R](RST)が返る、あるいは何も返らない場合は、ポートが閉じている / 経路で遮断されている可能性が高い。

見たい通信だけに絞るには?(BPFフィルタ)

結論: コマンド末尾に BPF 式を書くと対象を絞れる。host / port / src / dstand / or / not の組み合わせがほぼすべて。

tcpdump の引数末尾に書く条件式を BPF(Berkeley Packet Filter)という。代表的なものだけ覚えれば実務は回る。

# 特定ホストとの通信だけ
$ sudo tcpdump -i any -nn host 93.184.216.34

# 特定ポートだけ(HTTPS)
$ sudo tcpdump -i any -nn port 443

# 送信元 / 宛先を限定
$ sudo tcpdump -i any -nn src 192.168.1.10
$ sudo tcpdump -i any -nn dst port 53

# プロトコルを限定
$ sudo tcpdump -i any -nn udp port 53

条件を組み合わせる

# host A かつ port 443
$ sudo tcpdump -i any -nn host 192.168.1.10 and port 443

# 22番(SSH)以外を見たい
$ sudo tcpdump -i any -nn not port 22

# DNS か HTTPS
$ sudo tcpdump -i any -nn 'port 53 or port 443'

and / or / not を含む式や括弧を使う場合は、シェルの解釈を避けるため 式全体をシングルクォート で囲む(例: 'tcp port 80 and host 10.0.0.1')。

よく使う語彙: host / net 192.168.1.0/24 / port / portrange 8000-8100 / src / dst / tcp / udp / icmp / arp

中身(ペイロード)まで見るには?

結論: -A で ASCII、-X で16進+ASCII を表示。平文の HTTP ヘッダや DNS クエリの確認に有効。詳細度は -v / -vv で調整する。

ヘッダだけでなくパケットの中身を確認したいときに使う。

# ASCII でペイロード表示(HTTPヘッダ等の確認に)
$ sudo tcpdump -i any -nn -A port 80

# 16進数 + ASCII(バイナリ解析向け)
$ sudo tcpdump -i any -nn -X port 80

# 詳細度を上げる(TTL・オプション等)
$ sudo tcpdump -i any -nn -vv host 192.168.1.10

HTTPS(443)はペイロードが暗号化されているため -A / -X で中身は読めない(TLS のハンドシェイクや SNI の一部は見える)。平文が見えるのは HTTP・DNS など暗号化されていない通信。

古い情報で -s 0(スナップ長を無制限に)が必要とされることがあるが、近年の tcpdump は既定のスナップ長が十分大きく(262144 バイト)、通常は指定不要。

キャプチャを保存して後で解析するには?

結論: -w file.pcap でバイナリ保存、-r file.pcap で読み戻す。保存した pcap は Wireshark でそのまま開けるので、取得はサーバ・解析は手元という分業ができる。

保存と読み戻し

# pcap 形式で保存(画面には出さず書き出す)
$ sudo tcpdump -i any -nn -w capture.pcap

# 保存したファイルを読む(読むだけなら sudo 不要)
$ tcpdump -nn -r capture.pcap

# 読み込み時にもフィルタを後がけできる
$ tcpdump -nn -r capture.pcap port 443

取得はサーバ、解析は手元

  1. サーバで sudo tcpdump -i any -nn -w /tmp/cap.pcap port 443 -c 1000
  2. 手元へ転送(scp user@server:/tmp/cap.pcap .
  3. Wireshark で cap.pcap を開く

GUI のフィルタ・追跡機能で深く追えるので、込み入った解析はこの型が速い。

ファイルを回して溜めすぎない

長時間キャプチャはディスクを圧迫する。サイズや時間でローテーションできる。

# 100MB ごとにファイルを分割、最大10ファイルで循環
$ sudo tcpdump -i any -nn -w cap_%Y%m%d_%H%M%S.pcap -C 100 -W 10
  • -C 100:1ファイル約100MBで切り替え
  • -W 10:保持ファイル数の上限(超えると古いものから上書き)

切り分けの実例:接続できない

結論: 「SYN を送って応答が無い / RST が返る」かを見れば、到達性とポート開放を一気に切り分けられる。

ある相手の443番に繋がらないときの確認。

$ sudo tcpdump -i any -nn host 93.184.216.34 and port 443

判断の目安:

  • [S] を送って [S.] が返る → 到達・ポート開放はOK(問題はアプリ層)
  • [S] を送って [R](RST)が返る → 相手まで届いているがポートが閉じている
  • [S] を送るが何も返らない → 経路の途中(FW・経路設定)で落ちている可能性
  • 自分発の [S] すら出ない → ローカルの経路・名前解決・アプリ側を疑う

ping / traceroute での到達性確認と併用すると切り分けが速い。詳細は関連記事を参照。

よく使うオプション早見表

結論: -i / -nn / -c / -w / -r / -A / -v の7つを押さえれば日常のトラブルシュートは十分カバーできる。

オプション 役割
-i IF キャプチャするインターフェイス(any 可)
-nn ホスト名・ポート名を解決しない
-c N N 件で停止
-w FILE pcap 形式で保存
-r FILE pcap を読み込む
-A ペイロードを ASCII 表示
-X 16進数 + ASCII 表示
-v/-vv 詳細度を上げる
-e リンク層(MAC アドレス)も表示
-D 利用可能なインターフェイス一覧

コピペ用:安全テンプレ

# まず眺める
sudo tcpdump -i any -nn -c 50

# 対象を絞る
sudo tcpdump -i any -nn host 192.168.1.10 and port 443

# 保存して後で解析
sudo tcpdump -i any -nn -w /tmp/cap.pcap port 443 -c 1000
tcpdump -nn -r /tmp/cap.pcap

次に読む