tcpdumpとWiresharkを使ったネットワークトラフィック解析入門

Network tutorial - IT technology blog
Network tutorial - IT technology blog

5分ですぐに使い始める

サーバーにネットワーク問題が発生して、トラフィックの状況が分からない?まずターミナルを開いて実行してみよう:

# eth0インターフェース上のすべてのトラフィックをキャプチャ
sudo tcpdump -i eth0

# HTTPトラフィック(ポート80)とHTTPS(ポート443)のみを表示
sudo tcpdump -i eth0 'port 80 or port 443'

# 後でWiresharkで開くためにファイルに保存
sudo tcpdump -i eth0 -w /tmp/capture.pcap

この3つのコマンドだけで、サーバーを流れるトラフィックを確認できる。フィルタリングと解析こそが時間のかかる部分であり、同時に最も面白いところでもある。

tcpdump — GUIなしサーバーでの主力ツール

インストール

# Ubuntu/Debian
sudo apt install tcpdump -y

# CentOS/RHEL
sudo yum install tcpdump -y

# 利用可能なインターフェースを確認
sudo tcpdump -D

よく使うフィルター

tcpdumpはBerkeley Packet Filter(BPF)構文を使用している。最初は見慣れないが、10分もあればよく使うものはすべて覚えられる:

# ホストでフィルタリング(送受信両方)
sudo tcpdump -i eth0 host 192.168.1.100

# 特定のIPからのトラフィックのみを表示
sudo tcpdump -i eth0 src host 192.168.1.100

# 特定のIPへのトラフィックのみを表示
sudo tcpdump -i eth0 dst host 192.168.1.100

# サブネットでフィルタリング
sudo tcpdump -i eth0 net 192.168.1.0/24

# 複数条件を組み合わせる
sudo tcpdump -i eth0 'host 192.168.1.100 and port 443'

# ノイズにならないようSSHを除外
sudo tcpdump -i eth0 'not port 22'

読みやすい出力にする

# -n: DNS解決をしない(高速化)
# -nn: ポート名も解決しない
# -v: 詳細表示(情報を追加)
# -vv: さらに詳細表示
# -X: hexとASCIIの両方を表示
sudo tcpdump -i eth0 -nn -v 'port 80'

# ASCIIでペイロードを表示(HTTPに適している)
sudo tcpdump -i eth0 -A -nn 'port 80' | head -100

Wireshark — 深い解析が必要なとき

tcpdumpでキャプチャして、Wiresharkで解析する。私がよく使うワークフローは、ヘッドレスサーバー上でtcpdumpでキャプチャし、pcapファイルをローカルマシンにコピーして、Wiresharkで開く方法だ。こうすることでサーバーはGUI実行のリソースを消費せず、ゆっくり確認できる。

サーバーでキャプチャ、ローカルマシンで解析

# サーバー上:60秒キャプチャしてファイルに保存
sudo tcpdump -i eth0 -w /tmp/capture_$(date +%Y%m%d_%H%M%S).pcap -G 60 -W 1

# ローカルマシンにコピー
scp user@server:/tmp/capture_*.pcap ~/Desktop/

WiresharkでpcapファイルをW開き、Display Filterを使ってフィルタリングする:

# Wireshark内のフィルター(Display Filterバー)
http                          # HTTPのみ
tcp.port == 443               # HTTPS
ip.addr == 192.168.1.100      # IPアドレスでフィルタリング
tcp.flags.syn == 1            # SYNパケットのみ
http.response.code == 500     # HTTP 500エラー
dns                           # DNSクエリのみ

見逃せないWiresharkの機能

  • Follow TCP Stream:パケットを右クリック → Follow → TCP Stream。Wiresharkがクライアントとサーバーのすべてのやりとりを読みやすい1画面にまとめてくれる。HTTPリクエストのデバッグにこれを使えば、1時間以上の節約になる。
  • Statistics → Conversations:一目でどのIPが最も帯域幅を使っているかが分かる。小規模なDDoSや、何らかのプロセスが異常にデータを引っ張っているときに非常に役立つ。
  • Statistics → IO Graph:時間軸でトラフィックをグラフ化する。ログを1行ずつ読むよりも、異常なスパイクを見つけるのがはるかに簡単だ。
  • Analyze → Expert Information:WiresharkがTCPの再送信、接続リセット、ウィンドウサイズの問題を自動でハイライトしてくれる。フィルターを知らなくても、ここを見るだけで問題がいくつあるかが一目で分かる。

実践的なデバッグ:断続的なパケットロス

私が経験した最も難しいデバッグは、午後8〜9時だけに発生する断続的なパケットロスだった。昼間はpingが正常に通る。ピーク時間帯になると、一部の接続でラグが発生し始める。ping -i 0.2 -c 500を実行すると、ロス率はわずか0.3〜0.5%——ユーザーがラグを感じるには十分だが、基本的なtcpdumpで何かを検出するには低すぎる数値だった。

対処方法:

# 継続的にキャプチャし、5分ごとにファイルをローテーション、最大24ファイル(2時間分)を保持
sudo tcpdump -i eth0 -w /tmp/capture_%H%M.pcap -G 300 -W 24 \
  'not port 22 and not arp'

# パケットロスを検出するために並行して実行するスクリプト
ping -i 0.2 -c 1000 192.168.1.1 | grep -E 'packet loss|time='

問題発生の時間帯に対応するpcapファイルを入手し、Wiresharkで開いてフィルタリングする:

# TCP再送信を検出
tcp.analysis.retransmission

# 重複ACKを検出(パケットロスのサイン)
tcp.analysis.duplicate_ack

# すべてのTCP問題を検出
tcp.analysis.flags

結果は非常に明確だった:トラフィックスパイク時に再送信率が1%以下から13〜15%に跳ね上がっていた。タイムスタンプをさかのぼって追跡すると、システム内のスイッチがバッファ満杯時にパケットをドロップしていることが判明した。サーバーでも、アプリケーションでもなく——スイッチが原因だった。Wiresharkがなければ、さらに数日は調査が続いていただろう。

応用:SSH経由のリモートキャプチャ

サーバーにファイルを保存したくない?SSH経由でローカルマシンのWiresharkに直接パイプする:

# macOS/Linux上でローカルのWiresharkを開き、リモートサーバーからキャプチャ
ssh user@server 'sudo tcpdump -i eth0 -nn -w - not port 22' | wireshark -k -i -

# またはtshark(WiresharkのCLIバージョン)を使ってサーバー上で直接解析
sudo tshark -i eth0 -Y 'http.response.code >= 400' \
  -T fields -e ip.src -e http.response.code -e http.request.uri

tsharkでHTTPエラーを自動解析

# 解析のためにHTTPリクエストをCSVにエクスポート
sudo tshark -r /tmp/capture.pcap \
  -Y 'http.request' \
  -T fields \
  -e frame.time \
  -e ip.src \
  -e http.request.method \
  -e http.request.uri \
  -E header=y \
  -E separator=, \
  > /tmp/http_requests.csv

# メソッド別にリクエスト数をカウント
sudo tshark -r /tmp/capture.pcap \
  -Y 'http.request' \
  -T fields -e http.request.method | sort | uniq -c | sort -rn

実践的なヒント

1. ディスクがいっぱいにならないようキャプチャサイズを制限する:

# 100MBに制限し、5ファイルでローテーション
sudo tcpdump -i eth0 -w /tmp/cap.pcap -C 100 -W 5

2. ヘッダーのみキャプチャし、ペイロードはキャプチャしない——スペース節約、TCP解析には十分なデータ:

# -s 96: 各パケットの先頭96バイトのみキャプチャ
sudo tcpdump -i eth0 -s 96 -w /tmp/headers_only.pcap

3. 複数のインターフェースを同時にキャプチャ:

# 'any'を使ってすべてのインターフェースをキャプチャ
sudo tcpdump -i any -nn -w /tmp/all_interfaces.pcap

4. tsharkで遅延を素早く分析:

# TCPコネクション確立時間を確認(SYN → SYN-ACK)
sudo tshark -r /tmp/capture.pcap \
  -Y 'tcp.flags.syn==1 and tcp.flags.ack==1' \
  -T fields -e ip.src -e ip.dst -e tcp.time_delta

5. サーバーがNICオフロード(チェックサムオフロード)を使用している場合、tcpdumpが「bad checksum」と報告することがある——これはFalse Positiveであり、本物のエラーではない。混乱しないよう警告をオフにする:

sudo tcpdump -i eth0 --no-promiscuous-mode -K 'port 80'

この2つのツールを一度学べば、一生使い続けられる。tcpdumpはあらゆるLinuxサーバーで動作し、追加インストール不要、GUIも不要だ。Wiresharkは生のパケットの山を人間が読める形に変換してくれる。この2つを組み合わせれば、ほぼすべてのネットワーク障害を明らかにできる。

Share: