「ssコマンドやnetstatでポートが開いていることは確認できた。でも、パケットが本当に届いているかどうかは判断できない...」
ネットワークトラブルの調査で「パケットレベルで何が起きているか」を見たい場面は、現場では頻繁にあります。
この記事では、
tcpdump コマンド の実践的な使い方を解説します。基本的なパケットキャプチャの方法、ホスト・ポート・プロトコルを絞り込むBPFフィルタの指定、
.pcap ファイルへの保存とWiresharkでの分析連携、現場でよくある障害の切り分けパターンまで、RHEL 9.4 / Ubuntu 24.04 LTS の環境で動作確認した内容をまとめました。この記事のポイント
・tcpdump -i eth0 で指定インターフェースのパケットをキャプチャできる
・host/port/proto フィルタを組み合わせて必要な通信だけに絞り込める
・-w でファイル保存し、Wiresharkに渡して詳細分析できる
・実務では「-n -s0」を付けるのが鉄則。DNS逆引きの遅延と断片化を防ぐ
・「tcpdumpに映らない」という事実が、経路・FW側の問題を示す重要な手がかりになる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
tcpdumpとは?ネットワーク調査の基礎ツール
tcpdump は、ネットワークインターフェースを流れるパケットをリアルタイムに表示・保存するコマンドラインツールです。LinuxだけでなくmacOSや各種UNIXでも利用でき、サーバー上でインストール不要(多くの場合デフォルト)で使える点が強みです。Wiresharkと並ぶパケット解析の定番ツールですが、GUI不要でSSH接続環境でも使えるため、サーバー管理者には必須のスキルです。
ssコマンドとtcpdumpは何が違うのか
ネットワーク障害の調査では、まずssコマンドやnetstatでポートの開放状況を確認するのが定石です。ただし、ssが確認できるのは「ポートが開いているかどうか」という状態だけで、実際にパケットが届いているか・応答が返っているかは確認できません。
tcpdumpはカーネルのネットワークスタック(NIC直下)でパケットを捕まえるため、以下のことが直接確認できます。
・パケット到達確認:パケットが実際にサーバーのNICまで届いているか
・接続確認:SYN→SYN-ACK→ACKの3ウェイハンドシェイクが完了しているか
・通信内容の確認:HTTPリクエスト・DNSクエリの内容を確認する
・障害原因の特定:再送・タイムアウト・RST送信の発生箇所を突き止める
重要なのは「tcpdumpに映っていない」という事実です。パケットがNIC到達前にDropされているのであれば、原因は経路・ファイアウォール側にあります。これだけでサービス内部の問題か、経路/FWの問題かを即座に二分できます。
主な用途は次の通りです。
・接続確認:SYN/ACKのやり取りが正常に行われているか確認する
・ファイアウォール調査:パケットがサーバーに届いているかを確認する
・通信内容の確認:HTTPリクエスト・DNSクエリの内容を確認する
・障害原因の特定:再送・タイムアウト・RST送信の発生箇所を突き止める
tcpdumpのインストール確認
1. インストール状況の確認
多くのLinuxディストリビューションではデフォルトでインストール済みですが、念のため確認します。# インストール確認 $ which tcpdump /usr/sbin/tcpdump $ tcpdump --version tcpdump version 4.99.3 libpcap version 1.10.3 (with TPACKET_V3) OpenSSL 3.1.1 30 May 2023
2. インストールされていない場合
# RHEL / Rocky Linux / AlmaLinux $ sudo dnf install -y tcpdump # Ubuntu / Debian $ sudo apt install -y tcpdump
基本的な使い方
1. すべてのパケットをキャプチャする(基本形)
tcpdump の基本的な実行形式です。-i でネットワークインターフェースを指定します。# eth0インターフェースのパケットをキャプチャ $ sudo tcpdump -i eth0 # すべてのインターフェースをキャプチャ $ sudo tcpdump -i any
-i any を指定するとすべてのインターフェースを対象にしますが、大量のパケットが流れるため、後述のフィルタと組み合わせて使うのが基本です。2. インターフェース一覧を確認する
どのインターフェースが存在するか分からない場合は-D で確認します。RHEL 9系では eth0 ではなく ens3 や ens192 のような名前になっている場合があります。# 利用可能なインターフェース一覧を表示 $ sudo tcpdump -D 1.eth0 [Up, Running, Connected] 2.lo [Up, Running, Loopback] 3.any (Pseudo-device that captures on all interfaces) [Up, Running] 4.bluetooth-monitor (Bluetooth Linux Monitor) [none] 5.nflog (Linux netfilter log (NFLOG) interface) [none]
3. 実務で必ず付けるオプション: -n と -s0
実務でのtcpdump は必ず以下の2つのオプションを付けてください。・-n:ホスト名・ポート名のDNS逆引きを無効にする。逆引きのせいで出力が遅延し、パケットを見逃す原因になる
・-s0 または -s 65535:パケット全体を取得する(デフォルトは68バイトで切り捨てられる)
# 推奨: 必ず -n -s0 を付ける $ sudo tcpdump -i eth0 -n -s0
4. パケット内容を16進数+ASCIIで表示する(-X)
ペイロードの生データを確認したい場合は-X オプションを使います。バイナリプロトコルの解析や、テキストベースのHTTPヘッダを16進数と合わせて確認するときに便利です。# ペイロードを16進数+ASCIIで表示する $ sudo tcpdump -i eth0 -n -X port 80
フィルタを使って対象パケットに絞り込む
tcpdump の最大の強みは、BPF(Berkeley Packet Filter)という構文で対象パケットを絞り込めることです。1. ホスト(IPアドレス)でフィルタ
特定のIPアドレスとのやり取りだけを表示します。# 特定ホストとの通信のみ $ sudo tcpdump -i eth0 -n host 192.168.1.100 # 送信元を指定 $ sudo tcpdump -i eth0 -n src 192.168.1.100 # 送信先を指定 $ sudo tcpdump -i eth0 -n dst 192.168.1.200
2. ポート番号でフィルタ
# ポート80(HTTP)のみ $ sudo tcpdump -i eth0 -n port 80 # ポート範囲指定 $ sudo tcpdump -i eth0 -n portrange 8000-8080 # 送信先ポートを指定 $ sudo tcpdump -i eth0 -n dst port 443 # 送信先ポート25番(SMTP)に限定する $ sudo tcpdump -i eth0 -n dst port 25
3. プロトコルでフィルタ
# TCPのみ $ sudo tcpdump -i eth0 -n tcp # UDPのみ(DNSの確認など) $ sudo tcpdump -i eth0 -n udp # ICMPのみ(pingパケット) $ sudo tcpdump -i eth0 -n icmp
4. フィルタの組み合わせ(and / or / not)
複数の条件を論理演算子で組み合わせられます。SSHセッションで作業している場合はnot port 22 を必ずフィルタに入れる習慣をつけてください。自分の操作パケットが大量に混入して、目的の通信が埋もれます。# 192.168.1.100 との tcp 443番ポートの通信 $ sudo tcpdump -i eth0 -n tcp and host 192.168.1.100 and port 443 # SSH(22番)以外のすべての通信 $ sudo tcpdump -i eth0 -n not port 22 # 特定ホストへのUDPまたはICMP $ sudo tcpdump -i eth0 -n host 8.8.8.8 and \( udp or icmp \) # DNSとHTTPの両方を監視する $ sudo tcpdump -i eth0 -n "port 53 or port 80" # 特定ホストのMySQL(3306番)通信をSSH除外しながら確認する $ sudo tcpdump -i eth0 -n "tcp and host 192.168.1.100 and port 3306 and not port 22"
キャプチャ結果の出力を読む
1. 基本的な出力形式
tcpdump の出力例を確認します。$ sudo tcpdump -i eth0 -n port 80 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 15:23:11.482310 IP 192.168.1.102.54321 > 192.168.1.10.80: Flags [S], seq 3001234567, win 64240, options [mss 1460,sackOK,TS val 1234567 ecr 0,nop,wscale 7], length 0 15:23:11.482405 IP 192.168.1.10.80 > 192.168.1.102.54321: Flags [S.], seq 987654321, ack 3001234568, win 65535, options [mss 1460,sackOK,TS val 9876543 ecr 1234567,nop,wscale 7], length 0 15:23:11.482521 IP 192.168.1.102.54321 > 192.168.1.10.80: Flags [.], ack 987654322, win 502, length 0
・15:23:11.482310:タイムスタンプ(マイクロ秒単位)
・IP 192.168.1.102.54321 > 192.168.1.10.80:送信元IP.ポート → 送信先IP.ポート
・Flags [S]:TCPフラグ。S=SYN(接続開始)、S.=SYN-ACK、.=ACK、P=PSH(データ送信)、F=FIN(切断)、R=RST(強制切断)
・length 0:ペイロードのバイト数(0はヘッダのみのパケット)
2. 詳細表示(-v / -vv / -vvv)
-v を付けるとTTL・ToS・チェックサム等の詳細情報が表示されます。-vv でさらに詳細になります。# より詳細な情報を表示 $ sudo tcpdump -i eth0 -n -v port 53 # DNS応答内容まで表示 $ sudo tcpdump -i eth0 -n -vv port 53
3. パケット内容をASCIIで表示(-A)
HTTPのリクエスト内容など、テキストベースのプロトコルを確認する際に有効です。# パケット内容をASCIIで表示 $ sudo tcpdump -i eth0 -n -A port 80 # 例: 実際の出力(HTTP GETリクエストの場合) 15:30:22.112345 IP 192.168.1.102.55123 > 192.168.1.10.80: Flags [P.], ... ..GET /index.html HTTP/1.1 Host: www.example.com User-Agent: curl/7.81.0 Accept: */*
ファイルへの保存とWiresharkでの分析
1. パケットをファイルに保存する(-w)
-w オプションで .pcap 形式のファイルに保存できます。後からWiresharkや tcpdump -r で分析できるため、障害発生時の証拠保全にも使います。# ファイルに保存(キャプチャはCtrl+Cで停止) $ sudo tcpdump -i eth0 -n -s0 -w /tmp/capture_$(date +%Y%m%d_%H%M%S).pcap # 特定条件でフィルタしながら保存 $ sudo tcpdump -i eth0 -n -s0 -w /tmp/http_capture.pcap port 80 # 保存完了後の確認 $ ls -lh /tmp/http_capture.pcap -rw-r--r--. 1 root root 2.3M Apr 13 15:45 /tmp/http_capture.pcap
-C(ファイルサイズ制限)と -W(最大ファイル数)を組み合わせて、容量暴走を防いでください。# 10MBごとにローテーション、最大5ファイルで上書き(容量暴走防止) $ sudo tcpdump -i eth0 -n -s0 -w /tmp/cap-%n.pcap -C 10 -W 5
2. 保存したファイルを読み込む(-r)
# 保存済みファイルを読み込んで表示 $ sudo tcpdump -r /tmp/http_capture.pcap -n # フィルタを使って必要なパケットだけ抽出 $ sudo tcpdump -r /tmp/http_capture.pcap -n port 80 # 行数を制限して確認 $ sudo tcpdump -r /tmp/http_capture.pcap -n -c 50
-w で保存した pcap ファイルはWiresharkでも開けます。本番サーバーで採取してPCへ転送し、GUI環境で詳細なプロトコル解析を行う流れが定番です。現場でよく使う調査パターン
1. 特定のIPとの接続が確立するか確認する(TCPスリーウェイハンドシェイク)
「接続はされているはずなのに応答が来ない」というトラブルで、まず確認するのがTCPのハンドシェイクです。ssでポートが開いていることを確認したら、次にtcpdumpでパケットが届いているかを確認するのが正しい手順です。# ステップ1: ssでポートが開いているか確認する $ ss -tlnp | grep 80 # ステップ2: tcpdumpでパケットが来ているか確認する # 別のターミナルから curl などでアクセスしながら実行する $ sudo tcpdump -i eth0 -n port 80 -c 20
# ss の出力 → ポートは開いている LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("httpd",pid=1234,fd=4)) # tcpdump の出力 → 何も表示されない(パケットが届いていない) tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes ^C 0 packets captured 0 packets received by filter 0 packets dropped by kernel
切り分けの方向:
・クライアント側のルーティング設定を確認する
・サーバー側のfirewalldでポートが許可されているかを確認する(
firewall-cmd --list-ports)・中間のネットワーク機器(L3スイッチ、クラウドのセキュリティグループ等)のACLを確認する
一方、tcpdumpでSYNが届いているにもかかわらず応答がない場合は、接続確認コマンドでハンドシェイクの状態を確認します。
# サーバーへのHTTPS接続のハンドシェイクを確認 $ sudo tcpdump -i eth0 -n tcp and host 203.0.113.10 and port 443 # SYN が送られていない場合: クライアント側の問題(ルーティング・firewalld) # SYN は届いているが SYN-ACK が返らない場合: サーバー側のfirewalldかサービスが停止している可能性 # SYN-ACK の後に RST が来る場合: 接続を拒否されている(ACLや接続数制限など)
2. DNSクエリの確認
「特定のホスト名に疎通できない」「名前解決が遅い」という状況では、tcpdumpでDNSパケット(UDP/53)を捕まえ、クエリと応答のやり取りを直接確認します。digコマンドでも名前解決の動作確認はできますが、tcpdumpを使うとリゾルバへのクエリが実際に飛んでいるか・応答が返ってきているかをNICレベルで確認できる点で補完的に使えます。# DNSクエリとレスポンスを確認 $ sudo tcpdump -i eth0 -n -vv port 53 # 実際の出力例(www.example.comへのAレコード問い合わせ) 15:40:55.234567 IP 192.168.1.102.45678 > 192.168.1.1.53: 12345+ A? www.example.com. (33) 15:40:55.235890 IP 192.168.1.1.53 > 192.168.1.102.45678: 12345 1/0/0 A 93.184.216.34 (49)
応答が返ってこない場合の切り分け:
・クエリが飛んでいるがDNSサーバーからの応答がない → DNSサーバー側の問題(
dig @8.8.8.8 example.com で直接確認)・クエリ自体がtcpdumpに映らない → /etc/resolv.conf の設定を確認する
・クエリは飛んでいて応答も来ているが解決できない → アプリ側のタイムアウトやNSS設定を確認する
3. 一定時間だけキャプチャして自動停止する
長時間キャプチャをかけておく場合、件数制限や時間制限を組み合わせます。# 100パケット取得したら自動停止 $ sudo tcpdump -i eth0 -n -c 100 -w /tmp/sample.pcap # 30秒間だけキャプチャ(timeout コマンドと組み合わせ) $ sudo timeout 30 tcpdump -i eth0 -n -s0 -w /tmp/capture_30sec.pcap
トラブルシュート・よくあるエラー
「tcpdump: eth0: No such device exists」と表示される
指定したインターフェース名が間違っています。tcpdump -D または ip link コマンドで正しいインターフェース名を確認してください。RHEL 9系では eth0 ではなく ens192 や ens3 のような名前になっている場合があります。「tcpdump: listen: SIOCSIFFLAGS: Operation not permitted」と表示される
root権限がありません。sudo tcpdump で実行するか、root ユーザーに切り替えてください。出力が表示されない
対象のインターフェースにパケットが流れていないか、フィルタが厳しすぎる可能性があります。まずtcpdump -i any でフィルタなしで試し、パケットが流れていることを確認してから条件を絞り込んでください。キャプチャ中に大量の出力で埋まってしまう
SSHセッションで作業しているときに特に起きやすいです。not port 22 でSSH通信を除外し、-c 件数 でキャプチャ件数を制限してください。タイムスタンプを日付込みで表示したい場合は -tttt オプションが便利です。# パケット数を100件に制限して自動停止する $ sudo tcpdump -i eth0 -n port 80 -c 100 # SSH通信を除外して100件キャプチャする $ sudo tcpdump -i eth0 -n "not port 22" -c 100 # タイムスタンプを詳細(マイクロ秒+日付)で表示する $ sudo tcpdump -i eth0 -n -tttt port 80
-rで保存ファイルを読み込むと「magic number」エラーになる
ファイルが壊れている可能性があります。file コマンドでファイルタイプを確認してください。pcap capture file と表示されれば正常です。# キャプチャファイルのタイプを確認する $ file /tmp/capture.pcap # 正常な場合の出力 /tmp/capture.pcap: pcap capture file, microsecond ts (little-endian) - version 2.4 (Ethernet, capture length 262144)
TCPフラグの読み方
| フラグ表記 | 意味 | よく見るシーン |
|---|---|---|
[S] |
SYN(接続開始要求) | クライアントが接続を開始するとき |
[S.] |
SYN-ACK(接続受け入れ) | サーバーが接続を受け入れるとき |
[.] |
ACK(確認応答) | データ受信の確認 |
[P.] |
PSH-ACK(データ送信) | アプリケーションデータが送られるとき |
[F.] |
FIN-ACK(切断開始) | 正常な接続終了 |
[R.] |
RST-ACK(強制切断) | 接続拒否・異常終了のとき |
本記事のまとめ
| やりたいこと | コマンド |
|---|---|
| 指定インターフェースをキャプチャ | sudo tcpdump -i eth0 -n -s0 |
| 特定ホストとの通信だけ表示 | sudo tcpdump -i eth0 -n host 192.168.1.100 |
| ポート番号でフィルタ | sudo tcpdump -i eth0 -n port 443 |
| TCP/UDP/ICMPで絞り込む | sudo tcpdump -i eth0 -n tcp |
| SSH通信を除外する | sudo tcpdump -i eth0 -n "not port 22" |
| 複数条件を組み合わせる | sudo tcpdump -i eth0 -n host 1.2.3.4 and port 80 |
| 内容をASCIIで表示 | sudo tcpdump -i eth0 -n -A port 80 |
| ペイロードを16進数+ASCIIで確認 | sudo tcpdump -i eth0 -n -X port 80 |
| ファイルに保存 | sudo tcpdump -i eth0 -n -s0 -w /tmp/cap.pcap |
| 容量制限付きで保存(ローテーション) | sudo tcpdump -i eth0 -n -s0 -w /tmp/cap-%n.pcap -C 10 -W 5 |
| 保存ファイルを読み込む | sudo tcpdump -r /tmp/cap.pcap -n |
| 100件取得で自動停止 | sudo tcpdump -i eth0 -n -c 100 |
tcpdump はインストールされているサーバーであればGUI不要でパケットレベルの調査ができます。「tcpdumpに映らない」という事実は経路・FWの問題を示し、「映っているのに接続できない」ならサービス側・アプリ側の問題と切り分けられます。この二分の型を身につけるだけで、ネットワーク障害の初動対応が格段に速くなります。Linuxのネットワーク調査コマンドとして、
ss・ip・lsof とあわせて覚えておくと、現場での対応力が一段と上がります。Linuxのネットワーク調査では
tcpdump と合わせて、ssコマンド や ipコマンド も活用すると、より多角的な障害対応が可能になります。
tcpdumpで通信の流れは見えてきた。次はLinuxサーバー全体の構築・運用を体系的に押さえませんか?
パケットキャプチャは障害対応の強力な武器ですが、サーバー構築・セキュリティ設定・ログ管理まで体系的に身につけることが、本当の運用力につながります。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
<PR>手元に置いて学びを深める1冊
実践 パケット解析 第3版 —Wiresharkを使ったトラブルシューティング
tcpdumpでキャプチャしたパケットをWiresharkで深掘りする手順を体系的に習得できる定番書—まず無料メルマガで基礎を固め、さらに一歩踏み込みたいときに手元に置いておきたい1冊です。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 次のページへ:ssh-keygenコマンドでSSH公開鍵認証を設定する方法|鍵の生成からauthorized_keys設定まで
- 前のページへ:opensslコマンドでSSL/TLS証明書を確認する方法|有効期限・暗号スイート・接続テストも
- この記事の属するカテゴリ:Linuxtipsへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます