2026年9月24日

2026年9月24日

tcpdumpでパケットをキャプチャして分析する方法|サーバーの通信トラブル調査

tcpdump は、サーバー上で流れるパケットをその場で表示・保存できるコマンドラインのツールです。「外部 API への接続がタイムアウトする」「メールが送れない」「リモートの DB に繋がらない」といった問題で、通信がそもそも出ているのか、相手から応答があるのかを事実として確かめられます。この記事では、サーバー上で tcpdump を使うときのフィルタの書き方、出力の読み方、ファイルへの保存とローテーション、WordPress サーバーでよくある調査例を説明します。保存したファイルを GUI で詳しく見る方法は Wireshark の記事で扱うので、ここではサーバー上での取得と一次判断に絞ります。

使う前の注意

パケットには Cookie、フォームの入力内容、暗号化されていない通信の本文などの個人情報や秘密情報が含まれることがあります。次の点を守ってください。

  • キャプチャは自分が管理する、または調査の許可を得たサーバーとネットワークに限る。
  • 保存したファイルは権限を絞り、調査が終わったら削除する。社外に渡すときは中身を確認してから。
  • 本番サーバーでは、フィルタを絞り、件数や時間に上限をつけて実行する。全通信を長時間保存するとディスクと CPU を圧迫します。

インストールと基本形

多くのディストリビューションでは標準のパッケージで入ります。

sudo apt install tcpdump      # Debian / Ubuntu
sudo dnf install tcpdump      # RHEL 系
tcpdump --version
sudo tcpdump -D               # キャプチャできるインターフェース一覧

基本の形は次のとおりです。

sudo tcpdump -i eth0 -nn -c 20 port 443
  • -i eth0: インターフェースを指定します。名前は ip -br addr で確認します(ens3 や enp1s0 などの場合もあります)。-i any で全インターフェースを対象にできますが、表示形式が少し変わります。
  • -nn: IP アドレスとポート番号を名前に変換しません。名前解決を省くと表示が速くなり、DNS 問い合わせ自体がキャプチャに混ざるのも防げます。
  • -c 20: 20パケットで終了します。本番では件数か時間の上限をつけるのが安全です。
  • port 443: キャプチャフィルタ(BPF)です。後述します。

SSH で作業している場合、フィルタを付けずに実行すると自分の SSH 通信を表示し、その表示がまた通信を生む状態になります。not port 22 を付けるか、調べたい通信に絞ってください。

キャプチャフィルタの書き方

tcpdump のフィルタは BPF(Berkeley Packet Filter)の文法で、カーネル側で絞り込むため負荷を抑えられます。よく使う形を挙げます。

host 203.0.113.10                 # 送信元か宛先がこのIP
src host 203.0.113.10             # 送信元に限定
dst port 3306                     # 宛先ポート
port 80 or port 443               # どちらか
host 203.0.113.10 and not port 22
net 192.0.2.0/24                  # ネットワーク単位
udp port 53                       # DNS
'tcp[tcpflags] & (tcp-syn|tcp-rst) != 0'   # SYN か RST を含むパケット

and・or・not やかっこを使う場合は、シェルに解釈されないようフィルタ全体をシングルクォートで囲みます。

出力の読み方

TCP の接続は次のように表示されます(見やすく省略しています)。

10:15:01.100 IP 198.51.100.5.51234 > 203.0.113.10.443: Flags [S], seq 1000, win 64240, length 0
10:15:01.120 IP 203.0.113.10.443 > 198.51.100.5.51234: Flags [S.], seq 5000, ack 1001, win 65160, length 0
10:15:01.120 IP 198.51.100.5.51234 > 203.0.113.10.443: Flags [.], ack 5001, win 502, length 0
10:15:01.121 IP 198.51.100.5.51234 > 203.0.113.10.443: Flags [P.], seq 1001:1518, ack 5001, length 517

Flags の記号は次の意味です。

  • [S]: SYN(接続開始の要求)
  • [S.]: SYN-ACK(相手が接続を受け付けた)
  • [.]: ACK のみ
  • [P.]: データの送信(PUSH + ACK)
  • [F.]: FIN(接続の終了)
  • [R] / [R.]: RST(接続の拒否・強制切断)

この並びから、問題の場所を次のように判断できます。

  • **[S] を送っても応答が無く、同じ [S] が間隔を空けて繰り返される**: 途中でパケットが捨てられています。相手側か経路上のファイアウォール、またはクラウドのセキュリティグループを疑います。
  • **[S] に対してすぐ [R.] が返る**: 相手のホストには届いていますが、そのポートで待ち受けているプロセスがいません。サービスの停止やポート番号の誤りを疑います。
  • 3ウェイハンドシェイク後、データ送信の直後に切断される: TLS のネゴシエーション失敗など、アプリケーション層の問題の可能性があります。この先は Wireshark で TLS の中身を見ると切り分けやすくなります。
  • **[S] 自体が出ていない**: 自サーバーから送信されていません。名前解決に失敗している、アプリケーションの設定が違う、送信側のファイアウォールで止まっている、などが考えられます。

HTTPS の通信は暗号化されているため、tcpdump では本文は読めません。読めるのは IP アドレス、ポート、タイミング、パケットの大きさまでです。-A(ASCII 表示)や -X(16進とASCII)で本文を確認できるのは、平文の HTTP や SMTP などに限られます。

ファイルに保存する

その場で読み切れない量の通信は、ファイルに保存して後から分析します。

sudo tcpdump -i eth0 -nn -w /var/tmp/api.pcap 'host 203.0.113.10'
sudo tcpdump -nn -r /var/tmp/api.pcap | less           # 保存したファイルを読む
sudo tcpdump -nn -r /var/tmp/api.pcap 'tcp[tcpflags] & tcp-rst != 0'   # 読むときにも絞れる

現在広く使われているバージョン(2026年10月現在)では、既定でパケット全体を保存します。古い資料にある -s 0 は、パケット全体を取る指定として今でも使えます。逆に本文が不要でヘッダーだけ見たい場合は、-s 128 のように小さくするとファイルが軽くなり、個人情報を抱え込むリスクも減らせます。

つまずきやすい点

  • 書き込み権限のエラー: 多くのビルドでは、tcpdump は起動後に専用ユーザーへ権限を落としてからファイルを書きます。そのためホームディレクトリなどに書けず「Permission denied」になることがあります。/var/tmp のような書き込める場所を使うか、-Z で権限を落とす先のユーザーを指定します。
  • 長時間の取得: -C(ファイルサイズの上限)と -W(ファイル数)を組み合わせると、決まった数のファイルを使い回すリングバッファになります。
# 約100MBごとにファイルを切り替え、10個を使い回す
sudo tcpdump -i eth0 -nn -w /var/tmp/ring.pcap -C 100 -W 10 'port 443'

-C の単位は 1,000,000 バイトです。ファイル名には番号が付きます。再現するまで待つ調査ではこの形で動かしておき、問題が起きた時刻のファイルだけを見ます。-G(秒数で切り替え)とファイル名の日時書式を組み合わせる方法もあります。

WordPress サーバーでの調査例

外部 API への接続が遅い・失敗する

プラグインの更新確認や外部 API(wp_remote_get などの HTTP リクエスト)がタイムアウトするときは、送信が出ているかと応答の有無を見ます。

sudo tcpdump -i eth0 -nn 'udp port 53 or (tcp port 443 and tcp[tcpflags] & (tcp-syn|tcp-rst) != 0)'

DNS の問い合わせに応答が無ければ名前解決の問題、SYN に応答が無ければ経路やファイアウォールの問題と切り分けられます。

メールが送れない

SMTP の送信ポート(587 など)への接続を見ます。SYN に応答が無い場合は、VPS 事業者が送信ポートを制限していないかも確認します。

sudo tcpdump -i eth0 -nn 'tcp port 587 or tcp port 465 or tcp port 25'

リバースプロキシとバックエンドの間

Nginx から同じサーバー内のアプリケーションへ転送している場合、通信はループバック(lo)を通ります。

sudo tcpdump -i lo -nn -A 'tcp port 8080'

ループバック上の平文 HTTP であれば -A でリクエストとレスポンスのヘッダーを確認できます。Cookie なども表示されるので、画面共有や記録の扱いに注意してください。

まとめ

  • tcpdump は「通信が出ているか」「相手が応答しているか」を事実で確かめるための道具。
  • -nn、件数の上限、not port 22 を基本にし、BPF のフィルタで対象を絞る。
  • [S] に応答が無ければ遮断、[R.] なら待ち受け無し、と Flags の並びで切り分ける。
  • 暗号化された通信の本文は読めない。必要なのはタイミングと応答の有無。
  • 長時間の取得は -C と -W のリングバッファで行い、保存したファイルは調査後に削除する。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲