Linux基礎

【tcpdump】の見方, 使い方, Filter, オプション(ローテーション等), 解析方法について

Linuxのパケットキャプチャツール tcpdump

Windows 上でのパケットキャプチャは Wireshark がよく使われますが、Linux 上でのパケットキャプチャは tcpdump を使います。

名前から迷いますが UDP も普通にキャプチャできます。

また、tcpdump で取得したファイルは Windows 上の Wireshark で見ることもできます。

CentOS8でのインストール方法

# dnf -y install tcpdump

一般的なオプション

標準的な使い方 標準出力で見る場合

# tcpdump -i eth1 -nn -vvv

オプション "-i" はインタフェース名を指定します。VMware 等で作っている Linux の場合、デフォルトで他のインタフェースが指定されていたりしますので、このオプションでキャプチャしたいインタフェースを指定します。

複数インタフェースでキャプチャをしたい場合は -i any で全インタフェースを指定します。

tcpdump -i any -nn -vvv

オプション "-n" は IP アドレスの名前解決をしないコマンドです。これが無いと表示動作が遅くなります。"-nn" にすると TCP ポートアドレスの解決もしなくなります (例えば ssh と表示されるところが 22 と表示されます)。

オプション "-v" は IP ヘッダ等を表示、"-vv" は NFS や SMB 等のペイロードの中身を表示、"-vvv" はさらに細かいところまで表示してくれます。

止め方

Ctrl + C

標準的な使い方 ファイル出力する(Wiresharkで見る)場合

tcpdump -i eth1 -w test.pcap -v

オプション "-w" ではファイル名を指定します。.pcap という拡張しにしておけば Windows の Wireshark で関連付けされていますのでダブルクリックだけで開けるはずです。

オプション "-v" は "-w" と一緒に使うと、1 秒毎に何パケットキャプチャしたかをリアルタイム表示してくれます。

キャプチャするパケットの数を指定したいとき

tcpdump で大量のパケットがキャプチャされた場合、コンソールに戻すのに時間が掛かる場合があります。負荷も少なからずあるため、気になる場合は -c でパケットキャプチャする数を指定します。10 パケットだけキャプチャしたい場合は以下のように指定します。

# tcpdump -i eth1 -nn -vvv -c 10

フィルタ指定

大量のパケットキャプチャの中から、特定のパケットだけキャプチャしたい場合はフィルタを指定します。

特定IPアドレス (例:10.1.2.3) の送受信のパケットをキャプチャしたい場合

# tcpdump -i eth1 -nn -vvv host 10.1.2.3

特定ポート (例:http 80) のパケットをキャプチャしたい場合

# tcpdump -i eth1 -nn -vvv tcp port 80

tcp を外した場合は udp の 80 番ポートの通信もキャプチャされます。

AND 条件 (特定 IP アドレス かつ 特定ポートを除外) のパケットをキャプチャしたい場合

# tcpdump -i eth1 -nn -vvv \(host 10.1.2.3\) and \(not tcp port 22\)

自身が ssh アクセスしているインタフェースをキャプチャする場合、ssh 通信を除外すると見やすくなります。not を使えば対象を除外することができます。

さらに ARP も邪魔なときはさらに『 and \(not arp\) 』を付けます。

AND や OR 等の複数条件を使う場合、どこまでが 1 つの条件なのか区切りを付けないとコマンドが誤解する可能性があります。カッコを使えば明確になりそのようなことは無くなるので覚えておいたほうがよいでしょう。カッコを使う場合は \ でエスケープする必要があります。

OR 条件 (特定 IP アドレス もしくは 特定 NW アドレス) のパケットをキャプチャしたい場合

# tcpdump -i eth1 -nn -vvv \(host 10.1.2.3\) or \(net 172.16.0.0/16\)

ローテーションについて

時間によるローテーション

tcpdump では -G オプションで時間単位でのローテーションが可能です。以下の記述では、pcap ファイルを 1 時間毎に新規生成・分割し、1 日単位でローテーションしていきます。

# tcpdump -i eth0 -G 3600 -w capture-at-%H.pcap

-G はローテーションを実施する秒数 (つまり 1 時間おきにファイルを生成する)、-w でのファイル名指定の中の "%H" はファイル生成時刻の "?時" を意味します。つまり 14 時にファイル生成すれば "%H=14" です。

ファイル名に使える % で始まる変数は、"strftime 関数" で定義されているものです。例えば %a=曜日、%b=月、%d=日にち、%H= 24 時間表記の時間、%M=分、%S=秒 です。

なお、指定ファイル数分だけ取得できたら tcpdump を停止したい!という場合は -W オプションを使います。以下の例では 10 ファイル生成されたら tcpdump は停止します。

# tcpdump -i eth0 -G 3600 -W 10 -w capture.pcap

サイズによるローテーション

サイズによるローテーションを行うためには -C を使います。以下の例では、pcap ファイルを 1MB サイズ毎にローテーションします。

# tcpdump -i eth0 -C 1 -w capture-per-1MB.pcap

-C オプションではファイルサイズ (単位= 1,000,000 Bytes ≒ 1 MB)を指定します。-w で指定されたファイル名の最後に通し番号が付きます。例えば 2 番目に生成されたファイルは "capture-per-1MB.pcap2" となります。

tcpdump では単体機能でサイズによる上書きローテーション機能はありません。timeout コマンドと cron を組み合わせれば何とか、、といった感じです。以下の例では、pcap ファイルを 1MB サイズ毎に新規生成・分割し、1800 秒単位でローテーションが行われます。

timeout 1800 tcpdump -i eth0 -C 1 -w capture-per-1MB.pcap

このコマンド実行を cron で 30 分毎に実行すれば目的は適うはずです。

また、時間ローテーションのときと同様、指定のファイル数を生成した後に tcpdump を止めたい!という場合はやはり -W オプションを使います。以下の例では 10 ファイル生成したら tcpdump を止めます。

# tcpdump -i eth0 -C 1 -W 10 -w capture-per-1MB.pcap

-s オプションについて

昔の tcpdump は 1 パケットあたりに取得できるサイズがデフォルトで 68 Bytes でした。なので tcp/udp や http 等の中身までキャプチャするには "-s" オプションでサイズを指定する必要がありました。

# tcpdump -i eth1 -nn -vvv -s 1500

ですが最近では 262144 Bytes という十分すぎるサイズになっていますので指定は不要です。

取得したパケットの見方

[root@localhost ~]# tcpdump -i ens33 -nn -vvv -c 5
tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
07:07:33.679674 IP (tos 0x10, ttl 64, id 3853, offset 0, flags [DF], proto TCP (6), length 216)
192.168.169.128.22 > 192.168.169.1.31893: Flags [P.], cksum 0xd49d (incorrect -> 0xd5e2), seq 1606433180:1606433356, ack 847329430, win 262, length 176
07:07:33.680302 IP (tos 0x10, ttl 64, id 3854, offset 0, flags [DF], proto TCP (6), length 376)
192.168.169.128.22 > 192.168.169.1.31893: Flags [P.], cksum 0xd53d (incorrect -> 0x7939), seq 176:512, ack 1, win 262, length 336
07:07:33.680781 IP (tos 0x0, ttl 128, id 5973, offset 0, flags [DF], proto TCP (6), length 40)
192.168.169.1.31893 > 192.168.169.128.22: Flags [.], cksum 0x50d6 (correct), seq 1, ack 512, win 2060, length 0
07:07:33.680997 IP (tos 0x10, ttl 64, id 3855, offset 0, flags [DF], proto TCP (6), length 568)
192.168.169.128.22 > 192.168.169.1.31893: Flags [P.], cksum 0xd5fd (incorrect -> 0x2323), seq 512:1040, ack 1, win 262, length 528
07:07:33.681332 IP (tos 0x10, ttl 64, id 3856, offset 0, flags [DF], proto TCP (6), length 360)
192.168.169.128.22 > 192.168.169.1.31893: Flags [P.], cksum 0xd52d (incorrect -> 0x4780), seq 1040:1360, ack 1, win 262, length 320
5 packets captured
6 packets received by filter
0 packets dropped by kernel
[root@localhost ~]#

1 パケット目について詳細を見ていきます。

まずは時間が表示されます。(07:07:33.679674)

その次に IP ヘッダ情報が表示されます。ToS は 00010000, TTL は 64, flag は DF ビット (分割禁止)、プロトコルは TCP、パケット長は 216 Bytes と言うことが分かります。{IP (tos 0x10, ttl 64, id 3853, offset 0, flags [DF], proto TCP (6), length 216)}

その次に送信元 IP、送信元 TCP ポート、宛先 IP、宛先 TCP ポートが表示されます。(192.168.169.128.22 > 192.168.169.1.31893)

これは『送信元 IP = 192.168.169.128』『送信元 TCP ポート = 22』『宛先 IP = 192.168.169.1』『宛先 TCP ポート = 31893』という意味です。紛らわしいですが、IP アドレスとポート番号が.(ドット)で連結されているのです。

その次に TCP ヘッダ情報が表示されます。Push フラグが立っていること、TCP ペイロード長が 176 Bytes であることが分かります。{Flags [P.], cksum 0xd49d (incorrect -> 0xd5e2), seq 1606433180:1606433356, ack 847329430, win 262, length 176}

cksum で incorrect と表示されていますが、tcpdump を動かしているホストから送信されるパケットについてはこのエラーを無視して構いません。これは『TCP checksum offloading』という機能の影響によるもので、OS としてはこのチェックサム計算を行わずパケットキャプチャを出力し、その後 NIC のプロセッサにて計算し送信するためです。

コマンド生成ツール DA DUMP

tcpdumpを一度も使ったことの無い初心者でも簡単にコマンドを作成できます。

https://milestone-of-se.nesuke.com/knowhow/tcpdump-command-generator

コメント

タイトルとURLをコピーしました