アプリでエラーが出るのにpingが通る理由
次のようなトラブルは現場で日常茶飯事です。モバイルアプリでAPI呼び出し時にタイムアウトエラーが発生したとします。サーバーにSSH接続してデータベースや連携先APIのサーバーへpingを実行すると、パケットロスは0%、RTTもわずか2msと正常に応答します。しかし、バックエンドのログには相変わらずConnection timed outやConnection refusedが出力され続けます。
原因は極めてシンプルです。pingはICMPプロトコルを使用しているのに対し、アプリケーションはTCP/UDPで通信しているためです。ICMP Echo Requestが通るからといって、TCPの443番や5432番ポートが接続を受け付けているとは限りません。ファイアウォールが特定のアプリケーションポートのみ遮断している可能性もあれば、Webサーバーのバックログキューが溢れている可能性もあります。ネットワーク上で実際に何が起きているのかを正確に把握するには、tcpdumpを使って物理パケットを直接観察する必要があります。
tcpdumpのパケットキャプチャと解析の仕組み
tcpdumpは、libpcapライブラリをベースにした定番のCLIネットワーク解析ツールです。OSのネットワークスタックやiptablesによる詳細な処理が行われる前に、ネットワークカード(NIC)を出入りするデータフレームを直接インターセプトします。
TCP接続をデバッグする際は、角括弧[...]内に表示される次の4つの主要フラグに着目します。
- [S] (SYN): 3ウェイハンドシェイク(3-way handshake)の開始パケット。
- [S.] (SYN-ACK): サーバー側がハンドシェイクを承諾し、クライアントへ応答するパケット。
- [.] (ACK): 先行パケットを正常に受信したことを示す確認応答。
- [F] (FIN): 一方からの通常の接続終了要求。
- [R] (RST): 接続の即時リセット。ポートが開放されていない、受信プロセスが突然クラッシュした、あるいはファイアウォールが能動的にRSTを返してアクセスを拒否した際によく見られます。
実践:現場で使えるtcpdumpコマンド
1. クイックインストール
tcpdumpは主要なLinuxディストリビューションの標準リポジトリで提供されています。
# Ubuntu / Debian
sudo apt update && sudo apt install -y tcpdump
# RHEL / CentOS / Rocky Linux / AlmaLinux
sudo dnf install -y tcpdump
2. ネットワークインターフェースの確認
まず、対象サーバーにどのインターフェースが存在するかを確認します。
sudo tcpdump -D
実行すると、1.eth0、2.ens33、あるいはany(全インターフェースを対象)のように、インデックス番号付きで一覧が表示されます。
3. 必須の基本パラメータ
オプションを指定せずにtcpdumpを実行すると、ターミナルが一瞬でログに埋め尽くされます。必ず以下の最適化フラグを組み合わせて使用しましょう。
-i <interface>: 監視対象のネットワークインターフェースを指定(例:-i eth0、-i any)。-n: IPアドレスの名前解決を無効化し、ログ出力の遅延を防ぐ。-nn: ホスト名とポート番号の両方の名前解決を無効化(httpやhttpsではなく80、443と直接表示)。-c <パケット数>: 指定したパケット数をキャプチャしたら自動終了(例:-c 20)。-q: 簡易出力モード。パケットの重要な情報のみを簡潔に表示。
安全に素早く疎通確認を行うためのコマンド例(5パケットのみキャプチャ):
sudo tcpdump -i eth0 -nn -c 5
4. BPF(Berkeley Packet Filter)によるパケットフィルタリング
tcpdump最大の強みは、柔軟なBPFフィルタ構文にあります。and、or、notを使って複数条件を組み合わせることが可能です。
ケースA: 送信元・宛先IPによる絞り込み
特定のクライアント(例: 192.168.1.50)でAPI呼び出しエラーが発生している場合:
# IP 192.168.1.50 との送受信双方向トラフィックをすべてキャプチャ
sudo tcpdump -i eth0 -nn host 192.168.1.50
# クライアントからサーバーへのリクエストのみを追跡
sudo tcpdump -i eth0 -nn src host 192.168.1.50
# サーバーからクライアントへのレスポンスデータのみを追跡
sudo tcpdump -i eth0 -nn dst host 192.168.1.50
ケースB: Webサーバーの接続トラブル調査(ポート 80 / 443)
HTTP/HTTPSトラフィックのみを抽出し、TCPハンドシェイクの状態を確認します。
sudo tcpdump -i eth0 -nn "port 80 or port 443" -c 50
クライアントから[S]が繰り返し送信されているのにサーバーから[S.]が返ってこない場合、iptablesやUFWでパケットがDROPされている可能性が高いです。逆に、サーバーが即座に[R](RST)を返している場合は、NginxやApacheなどのプロセスがダウンしているか、指定ポートで適切にListenできていません。
ケースC: DNSタイムアウト障害の調査(ポート 53)
外部へのcurlコマンドでデータの取得開始までに5〜10秒もかかる場合、DNSの名前解決遅延が原因であることが多々あります。
sudo tcpdump -i eth0 -nn udp port 53
どのDNSリゾルバ(8.8.8.8やローカルリゾルバなど)へA/AAAAクエリが送信され、応答受信までに何ミリ秒要しているかを明確に確認できます。
5. Wireshark解析用のpcapファイル出力
複雑なTLSハンドシェイクやHTTPペイロードをターミナル上で追跡すると、重要な痕跡を見落としがちです。パケットをそのまま保存し、GUIで視覚的に解析できるWiresharkへエクスポートしましょう。
# ポート443で200パケットをキャプチャし、dump.pcapファイルへ書き出す
sudo tcpdump -i eth0 -nn -c 200 port 443 -w /tmp/dump.pcap
サーバー上でGUIを使わずに保存したファイルを直接確認したい場合:
tcpdump -nn -r /tmp/dump.pcap
6. 本番環境(Production)での運用上の注意点
高負荷な本番環境で安易にtcpdumpを実行すると、CPU使用率の急上昇や継続的なディスクI/Oによる容量逼迫を招く恐れがあります。例えば10,000 req/sを捌くAPIクラスターでは、わずか2分で数GB規模のpcapファイルが生成されてしまいます。
リソース枯渇によるサーバーダウンを防ぐため、以下の3原則を必ず遵守してください。
- 必ず
-cフラグを使用する: 既定のパケット数で自動停止させます(例:-c 500、-c 1000)。 - TCPヘッダーのみ保存する:
-s 96(snaplen 96バイト)を指定してデータペイロードを破棄し、ヘッダー部分のみをキャプチャします。ファイルサイズを80%以上削減できます。 - 無条件(フィルタなし)の全パケットキャプチャは避ける: 特定のIPやポートで必ず絞り込みを行います。
まとめ
tcpdumpは、Linuxシステムを運用するエンジニアにとって不可欠な診断ツールです。原因不明のネットワーク障害が発生した際も、数行のコマンドを実行するだけで、問題がアプリケーションコードにあるのか、内部ファイアウォールにあるのか、あるいはISP経路にあるのかを即座に切り分けることができます。基本的なBPF構文を押さえて、次回のオンコールや障害対応に備えておきましょう。

