【入門編】 tcpdumpのBpfフィルター式によるトラフィック絞り込み – トラブルシューティング&ネットワーク運用監視実践ガイド

みなさん、こんにちは!日夜、世界中を駆け巡るパケットの群れを見守り、時にはネットワークの「詰まり」や「迷子」をあざやかに解決するNOC(ネットワークオペレーションセンター)のシニアエンジニアです。

突然ですが、ネットワークの調子が悪いとき、みなさんはどうやって原因を突き止めていますか?
「Webサイトが表示されない…」「特定のサーバーとだけ通信が遅い…」
そんなとき、私たちはネットワーク上を流れる生データ、つまり「パケット」を直接のぞき見ることになります。そのための頼れる相棒が、コマンドラインで動くパケットキャプチャツール tcpdump です。

しかし、いざ tcpdump を実行してみると、画面には目にも留まらぬ速さで大量の文字が流れ去っていきます。
「うわっ、こんな大量のデータから、どうやって目的の通信を探せばいいの…?」と、圧倒されてしまいますよね。

そこで救世主となるのが、今回ご紹介する 「BPF(Berkeley Packet Filter)フィルター式」 です。
これは、膨大なパケットの洪水から「自分が今、本当に見たいパケットだけ」をきれいにすくい取ってくれる、魔法の「ふるい」のような仕組みです。

今回は、ネットワークやインフラに初めて触れるみなさんに向けて、小難しいビット数や複雑なヘッダーの専門用語は極力おいておき、「郵便配達」の身近な仕組みに例えながら、優しく一歩ずつ解説していきます。一緒にマスターして、現場で使えるエンジニアへの第一歩を踏み出しましょう!

—

そもそも「パケット」と「BPFフィルター」ってなに?

まずは、私たちが普段使っているネットワークの通信を、なじみ深い「郵便」に例えて考えてみましょう。

パケットは「手紙」

インターネット上でやり取りされるデータ(パケット)は、1通の「手紙」のようなものです。
手紙には、中身(メッセージ本文)だけでなく、封筒の表面にいろいろな情報が書かれていますよね。

  • 宛先と差出人の住所(どこから、どこへ送るのか?)
  • 宛先の部屋番号や担当窓口(その建物の、どの部屋に届けるのか?)
  • 配達の方法(速達なのか、書留なのか?)

ネットワークの世界でも全く同じです。パケットという封筒には、「IPアドレス(住所)」や「ポート番号(部屋番号)」、「プロトコル(配達方法)」といった宛名ラベルが貼られているのです。

BPFフィルターは「優秀な郵便仕分けロボット」

大規模なデータセンターやオフィスでは、毎秒数万通、数百万通もの手紙(パケット)が飛び交っています。これを全部開封して中身を確認するのは、どう考えても不可能です。

そこで活躍するのが BPF(Berkeley Packet Filter) です。
これは、パケットの宛名ラベル(住所や部屋番号)を瞬時に読み取り、「この住所宛ての手紙だけを私に見せて!」「この部屋番号以外のものは捨てて!」と、一瞬で仕分けてくれる超優秀な自動仕分けロボットなのです。

—

tcpdumpの基本コマンド

フィルターの使い方を学ぶ前に、まずは tcpdump を動かすための基本のコマンドを確認しておきましょう。

# 最もシンプルなキャプチャ実行コマンド
# (管理者権限が必要なため、sudo をつけて実行します)
sudo tcpdump -i eth0
  • sudo:管理者権限で実行します。
  • -i eth0:パケットを監視する「ネットワークカード(インターフェース)」の名前を指定しています。ここでは eth0 というカードを通る手紙を監視します。

このコマンドをそのまま実行すると、すべての手紙が画面に流れ込んできて大パニックになります。
そこで、このコマンドの一番後ろに、「仕分けのルール(BPFフィルター式)」を書き足していくことになります。

—

BPFフィルターの3大要素をマスターしよう!

仕分けのルールは、大きく分けて3つの要素で指定します。
郵便の例えと一緒に見ていくと、驚くほど簡単に理解できますよ!

1. 「だれ(Host)」を指定する:住所で仕分ける

手紙の「送信元」や「宛先」のIPアドレス(住所)を指定して仕分ける方法です。
これには host という言葉を使います。

# 192.168.1.10 という住所(IPアドレス)が関わっている手紙だけを仕分ける
sudo tcpdump -i eth0 host 192.168.1.10

さらに細かく、「この住所から発送された手紙だけ(送信元)」や、「この住所宛ての手紙だけ(宛先)」と指定することもできます。

  • src(source = 送信元):sudo tcpdump -i eth0 src host 192.168.1.10
  • dst(destination = 宛先):sudo tcpdump -i eth0 dst host 192.168.1.10

2. 「どこ(Port)」を指定する:部屋番号で仕分ける

IPアドレスが「建物全体の住所」なら、ポート番号は「建物のなかにある、特定の部屋番号や窓口」です。
例えば、Webサイトを見るための窓口は 80 番や 443 番、メールを送るための窓口は 25 番、といったように決まっています。
これには port という言葉を使います。

# 80番の部屋(Webサイトの通信)に関わる手紙だけを仕分ける
sudo tcpdump -i eth0 port 80

こちらも同様に、送信元(src)や宛先(dst)を限定することができます。

3. 「どうやって(Proto)」を指定する:配達方法で仕分ける

ネットワークの世界には、データの届け方にいくつかのルール(プロトコル)があります。

  • TCP:相手に届いたか一通ずつ確認しながら、確実・丁寧に送る方法(書留郵便のようなもの)
  • UDP:届いたかの確認はせず、スピード優先でどんどん送る方法(ハガキやチラシのポスティングのようなもの)
  • ICMP:ネットワークの生存確認などに使う、特別な挨拶状(ping コマンドなどで使われます)

これらは、そのまま tcp、udp、icmp という言葉をフィルターに書くだけで仕分けることができます。

# TCPという丁寧な配達方法(プロトコル)で送られている手紙だけを仕分ける
sudo tcpdump -i eth0 tcp

—

現場のエンジニアが毎日使う!「フィルターの組み合わせ」

ここからが、NOCの現場で生き抜くための本番です。
実際のトラブルシューティングでは、「この住所宛てで、かつ、Webの部屋番号を使っている手紙だけを見たい」というように、複数の条件を組み合わせて絞り込みます。

条件を繋ぐときは、次の3つの接続詞を使います。

  • and(かつ):両方の条件を満たすもの
  • or(または):どちらか一方の条件を満たすもの
  • not(〜以外):その条件に当てはまらないもの

それでは、実務で本当によく使う「鉄板の組み合わせパターン」を見ていきましょう!

パターンA:特定のWebサーバーとの通信だけを追いかける

「自社のWebサーバー(192.168.1.100)が、Webページ(ポート 80 または 443)を正しく返せているか確認したい!」というケースです。

# 「IPアドレスが 192.168.1.100」で、かつ「ポートが 80 または 443」の通信をキャプチャ
sudo tcpdump -i eth0 host 192.168.1.100 and \( port 80 or port 443 \)

> ★ポイント:
> and と or を組み合わせる時は、計算の順序をはっきりさせるためにカッコ ( ) で囲みます。
> ただし、Linuxの画面(ターミナル)でカッコをそのまま書くとエラーになってしまうため、カッコの前にバックスラッシュ(\)をつけて「これはただのカッコだよ」と教えてあげる必要があります。

パターンB:DNSのトラブル(名前解決ができない)を追いかける

「インターネットは繋がっているっぽいけど、ドメイン名(URL)からIPアドレスに変換できない(DNSエラー)」という時は、ポート 53 番(DNSの部屋番号)を流れる udp の通信を確認します。

# DNSサーバー(192.168.1.1)との間の、DNS通信(ポート53番、UDP)だけを追いかける
sudo tcpdump -i eth0 host 192.168.1.1 and udp and port 53

パターンC:自分の通信を除外して画面をすっきりさせる(超重要!)

実務で一番やってしまいがちな失敗が、「自分のSSH接続の通信で画面が埋め尽くされる」という現象です。
私たちが作業用のサーバーに接続するときは、SSH(ポート 22 番)を使っています。
何も考えずに tcpdump を実行すると、「キャプチャしたデータを私たちの画面に送るためのSSHパケット」自体を tcpdump がキャプチャしてしまい、画面が無限ループのように超高速でスクロールしてしまいます。

これを防ぐために、「ポート 22(SSH)以外」というフィルターを必ずかけるのが、現場のプロの合言葉です。

# SSH接続(ポート22)「以外」のすべての通信をキャプチャする
sudo tcpdump -i eth0 not port 22

このコマンドを実行するだけで、自分の操作による余計なノイズが一切消え去り、調査したい通信だけが静かに画面に現れるようになります。

—

NOCの先輩からアドバイス:実践での3つの心得

最後に、実際のトラブル対応で役に立つ、ちょっとしたコツを伝授します。

① -n オプションを必ずつけよう!

デフォルトの tcpdump は、IPアドレス(例: 192.168.1.10)を人間が見やすい「名前(例: mail.example.com)」に自動で変換しようと頑張ってしまいます。
しかし、ネットワークが障害でバタバタしているときにこの変換処理が走ると、動作が非常に重くなってしまいます。

そこで、「名前解決をしない(数字のまま表示する)」 という意味の -n オプションを常につける癖をつけましょう。

# 名前解決を無効化(-n)して、SSH(22番)を除外してキャプチャ
sudo tcpdump -ni eth0 not port 22

② パケットは「ファイルに保存」して持ち帰るのがプロ

本番環境のサーバー上で、流れるログを動体視力だけで追いかけるのは限界があります。
障害対応時は、一度パケットをファイルに保存してダウンロードし、PC上の「Wireshark」などのグラフィカルなツールでじっくり解析するのが一般的です。

# キャプチャしたパケットを「packet.pcap」というファイルに書き出す(-w)
sudo tcpdump -ni eth0 not port 22 -w packet.pcap

保存された .pcap ファイルは、まるで通信のドライブレコーダーのように、後からいつでもスロー再生して詳細に分析することができます。

③ 終わったら必ず「Ctrl + C」で停止する

tcpdump は、私たちが止めるまでずっとパケットを監視し、保存し続けます。
特にファイルへの書き出しを行っている場合、放置するとサーバーのハードディスクを使い果たしてしまう原因になります。用事が済んだら、キーボードの Ctrl キーを押しながら C を押して、きれいに終了させましょう。

—

まとめ

難しそうに見える tcpdump と BPFフィルターですが、仕組みを紐解いてみれば「住所(IP)」「部屋番号(Port)」「配達方法(Proto)」という、現実世界の郵便とまったく同じシンプルなルールで動いていることが分かりますよね。

  • 基本は host、port、proto の3つ。
  • それらを and、or、not で繋ぐだけ。
  • 自分のSSH接続を隠す not port 22 は現場の必須テクニック!

まずは開発環境やご自身の検証用サーバーで、簡単な ping を打ちながら tcpdump を動かしてみてください。
「あ、今パケットが届いた!」という瞬間を自分の目で捉えたとき、ブラックボックスだったネットワークの世界が、一気にクリアに見えてくるはずです。

一歩ずつ、楽しみながら理解を深めていきましょう。頼もしいインフラエンジニアへの道を、応援しています!

コメント

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