ネットワークのトラブルシューティングやセキュリティ分析を行う際、ネットワーク上を流れる実際のデータ(パケット)を確認することが非常に重要です。tcpdumpは、このパケットキャプチャを実現するための強力なコマンドラインツールです。多くのUnix系OS(Linux、macOSなど)に標準で搭載されているか、簡単にインストールできます。GUIを持たないため軽量で、リモートサーバーやリソースが限られた環境での利用に適しています。
このブログ記事では、tcpdumpの基本的な使い方から、よく使われるオプション、強力なフィルタリング機能、そして実践的な利用例までを詳しく解説していきます。
- ネットワーク接続問題のトラブルシューティング(例:「特定のサーバーに繋がらない」「通信が遅い」など)
- セキュリティ監視(例:不正なスキャン、マルウェア通信の検出)
- プロトコルの動作分析(例:TCPの3ウェイハンドシェイク、DNSクエリ応答の確認)
- リモートサーバーでのパケットキャプチャ
基本的な使い方
tcpdumpを使用するには、通常、ネットワークインターフェースにアクセスするための管理者権限(root権限)が必要です。コマンドの前に sudo をつけることが一般的です。
1. 利用可能なインターフェースの確認
まず、どのネットワークインターフェースでパケットをキャプチャするかを確認します。-D オプションを使用します。
sudo tcpdump -D
実行すると、番号付きでインターフェース名(例: eth0, en0, wlan0)とその説明が表示されます。
2. キャプチャの開始
キャプチャしたいインターフェースを指定してtcpdumpを実行します。-i オプションでインターフェース名を指定します。
sudo tcpdump -i eth0
上記コマンドは、eth0 インターフェースを流れるすべてのパケットをリアルタイムで画面に出力します。-i を省略した場合、tcpdump は通常、ループバックインターフェース(lo)を除いた中で最も番号の若い、アクティブなインターフェースを自動的に選択します。
3. キャプチャの停止
キャプチャを停止するには、Ctrl + C を押します。
4. 特定のパケット数で停止
-c オプションを使うと、指定した数のパケットをキャプチャした後に自動的に停止します。これは、テストや短時間の調査に便利です。
sudo tcpdump -i eth0 -c 100
この例では、100個のパケットをキャプチャするとtcpdumpは終了します。
よく使われるオプション
tcpdumpには非常に多くのオプションがありますが、ここでは特によく使われるものを紹介します。
| オプション | 説明 |
|---|---|
-i <interface> |
キャプチャ対象のネットワークインターフェースを指定します。(例: -i eth0) |
-n |
IPアドレスやポート番号を名前に解決しません(例: www.google.com ではなく 142.250.196.142、http ではなく 80 と表示)。解析が速くなり、DNSクエリも発生しません。 |
-nn |
-n に加えて、ポート番号もサービス名に解決しません。通常は -nn を使うことが多いです。 |
-c <count> |
指定した数のパケットをキャプチャしたら終了します。(例: -c 100) |
-w <filename> |
キャプチャしたパケットを画面に表示せず、指定したファイルにバイナリ形式(pcap形式)で保存します。(例: -w capture.pcap)。ファイル拡張子は .pcap が一般的です。 |
-r <filename> |
-w オプションで保存したpcapファイルを読み込んで表示します。(例: -r capture.pcap) |
-A |
パケットの内容をASCII文字で表示します。HTTPリクエスト/レスポンスなどのテキストベースのプロトコルを確認する際に便利です。 |
-X |
パケットの内容を16進数とASCII文字の両方で表示します。-Aよりも詳細な分析が可能です。 |
-v, -vv, -vvv |
表示する情報の詳細度を上げます。-vが多いほど、TTL(Time To Live)、IPヘッダオプション、TCPオプションなど、より多くの情報が表示されます。 |
-s <snaplen> |
各パケットからキャプチャするデータの最大バイト数を指定します (snapshot length)。デフォルト値(通常は大きい値ですが、古いバージョンでは68や96バイトの場合あり)ではパケット全体がキャプチャされないことがあります。-s 0 を指定すると、パケット全体をキャプチャしようとします(MTUサイズに依存)。完全なペイロード分析が必要な場合に重要です。 |
-p |
インターフェースをプロミスキャスモード(無差別モード)にしません。通常、tcpdumpは他のマシン宛のパケットもキャプチャするためにプロミスキャスモードを使用しますが、このオプションを指定すると自身宛のパケットのみをキャプチャしようとします。 |
-e |
データリンク層のヘッダ(例: イーサネットヘッダのMACアドレス)も表示します。 |
-U |
「パケットバッファリングなし」モード。-w でファイルに書き出す際に、パケットを受信するたびに即座にファイルに書き込みます。デフォルトではバッファリングされるため、リアルタイム性が求められる場合や、tcpdumpを強制終了した際に最後のパケットが失われるのを防ぎたい場合に有用です。 |
フィルタリング:目的のパケットだけを捉える
ネットワークトラフィックは膨大になることが多いため、目的のパケットだけを効率的にキャプチャするフィルタリング機能が非常に重要です。tcpdumpはBPF (Berkeley Packet Filter) と呼ばれる強力なフィルタ構文をサポートしています。
フィルタ式は通常、コマンドの最後に記述します。式は「タイプ」「方向」「プロトコル」などのキーワード(プリミティブ)と、それらを組み合わせる論理演算子(and, or, not)で構成されます。
基本フィルタ
| 種類 | キーワード | 説明 | 例 |
|---|---|---|---|
| タイプ | host <ip_or_hostname> |
指定したホスト(IPアドレスまたはホスト名)が送信元または宛先であるパケット。 | host 192.168.1.10 |
net <network>[/len] |
指定したネットワークアドレスに属するパケット。CIDR形式 (例: 192.168.1.0/24) やドット区切り (例: 192.168.1) で指定可能。 |
net 10.0.0.0/8 |
|
port <port_number> |
指定したポート番号(送信元または宛先)を使用するTCPまたはUDPパケット。 | port 80 |
|
| 方向 | src <qualifier> |
指定した条件が送信元(Source)であるパケット。 | src host 192.168.1.10 |
dst <qualifier> |
指定した条件が宛先(Destination)であるパケット。 | dst net 10.0.0.0/16 |
|
| (指定なし) | 送信元または宛先が条件に一致する場合。 | host 8.8.8.8 (送信元でも宛先でもOK) |
|
| プロトコル | tcp |
TCPプロトコルのパケット。 | tcp |
udp |
UDPプロトコルのパケット。 | udp port 53 |
|
icmp |
ICMPプロトコルのパケット(pingなどで使用)。 | icmp |
|
arp, ip, ip6 など |
その他のプロトコルを指定。 | arp |
論理演算子
and(または&&): 両方の条件を満たす場合に一致。or(または||): いずれかの条件を満たす場合に一致。not(または!): 条件を満たさない場合に一致。
複数の条件を組み合わせる場合は、括弧 () を使って優先順位を明確にすることが推奨されます。シェルによっては括弧が特殊文字として解釈されるため、フィルタ式全体をシングルクォート ' ' またはダブルクォート " " で囲むのが安全です。
# 例: 192.168.1.10 から送信され、宛先ポートが80または443のTCPパケット
sudo tcpdump -nn -i eth0 'src host 192.168.1.10 and tcp and (dst port 80 or dst port 443)'
# 例: ポート22 (SSH) を除くすべてのTCPパケット
sudo tcpdump -nn -i eth0 'tcp and not port 22'
TCPフラグによるフィルタ
TCPの接続確立(SYN)、切断(FIN, RST)などの特定の状態のパケットをフィルタリングすることも可能です。これは少し高度な構文を使います。
# SYNパケットのみをキャプチャ (接続開始)
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'
# FINパケットのみをキャプチャ (接続終了)
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-fin != 0'
# RSTパケットのみをキャプチャ (接続リセット)
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-rst != 0'
実践的な利用例
これまでに学んだオプションとフィルタを組み合わせて、実際のシナリオでtcpdumpを使ってみましょう。
例1: 特定ホストとのHTTP通信をキャプチャしてファイルに保存
IPアドレス 198.51.100.50 との間で行われるHTTP (ポート80) の通信を、名前解決せずに http_traffic.pcap ファイルに保存します。
sudo tcpdump -i eth0 -nn -w http_traffic.pcap 'host 198.51.100.50 and tcp port 80'
例2: DNSクエリと応答をASCIIで表示
DNS (ポート53) の通信内容を、詳細表示(-vv) かつASCII (-A) で画面に出力します。
sudo tcpdump -i eth0 -nn -vv -A 'udp port 53'
例3: 特定ネットワークからのping (ICMP Echo Request) のみをキャプチャ
10.1.1.0/24 ネットワークから送信されるICMP Echo Request (Type 8) パケットのみをキャプチャします。
sudo tcpdump -i eth0 -nn 'src net 10.1.1.0/24 and icmp and icmp[icmptype] == icmp-echo'
例4: pcapファイルを読み込み、特定のTCP接続を表示
以前保存した capture.pcap ファイルから、特定の送信元IPとポート、宛先IPとポートを持つTCP接続に関連するパケットのみを表示します。
tcpdump -nn -r capture.pcap 'tcp and src host 192.168.1.50 and src port 12345 and dst host 198.51.100.10 and dst port 80'
例5: パケット内容を16進数とASCIIで表示しつつファイルにも保存
パケットの内容を確認しながらファイルにも保存したい場合、tee コマンドや --print オプション(比較的新しいバージョンのtcpdumpで利用可能)を使用します。
# tee を使う方法 (伝統的)
sudo tcpdump -i eth0 -nn -X -U -w - | tee capture.pcap | tcpdump -nn -X -r -
# --print オプションを使う方法 (新しいバージョン)
sudo tcpdump -i eth0 -nn -X --print -w capture.pcap
teeを使う方法では、-w -で標準出力にバイナリを書き出し、teeでファイルとパイプに分岐させ、パイプから再度tcpdump -r -で読み込んで表示します。-Uオプションでバッファリングを無効にするのがポイントです。--printオプションが使える場合はよりシンプルです。
出力の読み方
tcpdumpのデフォルト出力形式は、一般的に以下のようになっています(オプションによって変動します)。
timestamp protocol src_ip.src_port > dst_ip.dst_port: flags data_summary
- timestamp: パケットがキャプチャされた時刻 (
-t,-tt,-ttt,-tttt,-tttttで形式変更可能) - protocol: プロトコル名 (例: IP, TCP, UDP, ICMP, ARP)
- src_ip.src_port: 送信元IPアドレスとポート番号 (
-n,-nnで名前解決を抑制) - dst_ip.dst_port: 宛先IPアドレスとポート番号 (
-n,-nnで名前解決を抑制) - flags: プロトコル固有のフラグ (例: TCPフラグ [S.]=SYN+ACK, [P.]=PUSH+ACK, [F.]=FIN+ACK, [R]=RST)
- data_summary: パケットデータに関する簡単な要約 (例: TCPシーケンス番号、ACK番号、ウィンドウサイズ、データ長、UDPデータ長など)
例えば、TCPの3ウェイハンドシェイクは以下のように表示されることがあります (-nn オプション使用時)。
14:28:01.123456 IP 192.168.1.100.54321 > 198.51.100.50.80: Flags [S], seq 1000, win 65535, options [mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 7], length 0
14:28:01.123500 IP 198.51.100.50.80 > 192.168.1.100.54321: Flags [S.], seq 2000, ack 1001, win 65535, options [mss 1460,sackOK,TS val 200 ecr 100,nop,wscale 7], length 0
14:28:01.123550 IP 192.168.1.100.54321 > 198.51.100.50.80: Flags [.], ack 2001, win 512, options [nop,nop,TS val 101 ecr 200], length 0
-A や -X オプションを使用すると、これらの行に続いてパケットのペイロードデータが表示されます。
高度なTIPSと注意点
ファイルへの保存とWiresharkでの解析
-w オプションでキャプチャしたpcapファイルは、tcpdump自身で -r を使って読み返すこともできますが、より詳細なグラフィカル分析にはWiresharkが非常に便利です。Wiresharkは多くのOSで利用可能なGUIパケット解析ツールで、tcpdumpで保存したpcapファイルを直接開くことができます。複雑な通信シーケンスの追跡や、特定プロトコルの詳細なデコード、統計情報の表示などに優れています。リモートサーバーでtcpdumpを使って軽量にキャプチャし、そのファイルをローカルPCのWiresharkでじっくり分析する、という使い方が一般的です。
キャプチャファイルのローテーション
長時間のキャプチャを行う場合、単一のファイルが非常に大きくなる可能性があります。tcpdumpにはファイルサイズや時間でファイルを自動的に分割(ローテーション)するオプションがあります。
-C <file_size>: ファイルサイズが指定した値 (メガバイト単位) を超える前に、次のファイルに切り替えます。-wオプションと組み合わせて使用し、ファイル名に連番が付与されます (例:capture.pcap,capture.pcap1,capture.pcap2…)。-G <seconds>: 指定した秒数ごとにファイルをローテーションします。ファイル名は-wオプションで指定した書式(strftime形式)に従って生成されます。-W <count>: ローテーションするファイルの最大数を指定します。これを超えると古いファイルが上書きされます。
# 100MBごとにファイルをローテーションし、最大10ファイルまで保存する
sudo tcpdump -i eth0 -W 10 -C 100 -w capture.pcap
# 1時間(3600秒)ごとにファイルをローテーションし、ファイル名に日時を含める
sudo tcpdump -i eth0 -G 3600 -w 'capture_%Y%m%d_%H%M%S.pcap'
パフォーマンスへの影響
tcpdumpは軽量ですが、非常に高速なネットワーク(例: 10Gbps以上)やCPUリソースが限られた環境でフィルタなしに全パケットをキャプチャしようとすると、パケットロスが発生したり、システムのパフォーマンスに影響を与えたりする可能性があります。不要なパケットをキャプチャしないように、できるだけ具体的なフィルタを使用することが推奨されます。また、-s オプションでキャプチャサイズを必要最小限に制限することも有効です。
セキュリティとプライバシーに関する注意
まとめ
tcpdumpは、ネットワークエンジニアやシステム管理者にとって不可欠なツールの一つです。コマンドラインベースでありながら、その豊富なオプションと強力なフィルタリング機能により、ネットワーク上の問題を診断し、通信内容を詳細に分析するための強力な武器となります。
基本的な使い方から始め、オプションやフィルタを組み合わせることで、様々な状況に対応できます。また、キャプチャしたデータをWiresharkなどのGUIツールで分析することで、より深い洞察を得ることも可能です。
この記事が、tcpdumpを使いこなすための一助となれば幸いです。実際に様々なオプションやフィルタを試して、その挙動を確認しながら学習を進めていくことをお勧めします。Happy packet capturing!