Berkeley Packet Filters (BPF)

WiresharkBeginner
オンラインで実践に進む

はじめに

Berkeley Packet Filters (BPF) の実験へようこそ!

混雑した騒がしいスタジアムの中で、特定の誰かとの会話を聞き取ろうとすることを想像してみてください。生のネットワークトラフィックを解析するというのは、まさにそのような感覚です。忙しいサーバーでは、毎秒数千ものパケットが処理されています。必要な特定のデータを見つけるには、非常に精密な「ふるい」が必要です。

そこで登場するのが Berkeley Packet Filters (BPF) です。BPF は、深く統合された非常に効率的な技術であり、特殊な漁網のようにルールを設定して、関心のあるネットワークトラフィックだけをキャッチし、それ以外を無視することができます。

重要なのは、フィルタリングが単なる利便性のための機能ではないという点です。それは、問題が発生する前にノイズを削減するための手段です。フィルタがなければ、パケット解析はすぐに情報過多に陥ります。フィルタを使用すれば、巨大で混沌としたストリームを「このホストからのトラフィックを表示する」「このポートへの Web リクエストのみを表示する」といった、焦点を絞った問いに変えることができます。この能力こそが、大規模な本番環境であっても tcpdump が依然として有用である主な理由の一つです。

この実験では、tcpdump を使用してこれらの BPF ルールを作成する練習をします。特定の IP アドレスによる混沌としたネットワークストリームのフィルタリング、トラフィックの方向(送信か受信か)の制御、特定のアプリケーションポートのターゲット指定方法を学びます。最後には、これらのルールを組み合わせて、必要なイベントだけを外科手術のように正確に抽出する方法を習得しているはずです。

IP アドレス(ホスト/ネットワーク)によるフィルタリング

トラフィックをフィルタリングする最も基本的な方法は、IP アドレスで識別される特定のマシンに焦点を当てることです。フィルタを指定せずに tcpdump を実行すると、目に見えるすべてのパケットを容赦なく取得します。特定のマシンに関連するトラフィック以外を無視するように指示するには、host キーワードの後に IP アドレスを指定します。

ここで、初心者が混同しやすい 2 つの概念を整理しておきましょう。「インターフェース」はリッスン(監視)する場所であり、「IP フィルタ」はそのリッスンポイントからどの会話を取得したいかを記述するものです。言い換えれば、-i lo はマイクをどこに置くかを決め、host 127.0.0.1 はその部屋のどの話し手の声を聞きたいかを決めるものです。

観察対象のトラフィックを確保するため、環境内ではバックグラウンドスクリプトが既に実行されています。これは、常に内部 IP アドレス 127.0.0.1(localhost とも呼ばれます)を持つローカルマシンにデータを送信し続けています。

このローカルホストに関連するパケットを 5 つキャプチャしてみましょう。-i lo を使用してローカルループバックインターフェースをリッスンし、-c 5 を使用して自動的に停止させます。

ターミナルで以下のコマンドを実行してください:

sudo tcpdump -i lo -c 5 host 127.0.0.1

画面には以下のような出力が表示されます:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:15:32.123456 IP localhost.45678 > localhost.http-alt: Flags [S], seq 123456789, win 65495, options [mss 65495,sackOK,TS val 123456 ecr 0,nop,wscale 7], length 0
10:15:32.123489 IP localhost.http-alt > localhost.45678: Flags [S.], seq 987654321, ack 123456790, win 65483, options [mss 65495,sackOK,TS val 123456 ecr 123456,nop,wscale 7], length 0
10:15:32.124000 IP localhost > localhost: ICMP echo request, id 1234, seq 1, length 64
...
5 packets captured

リストされたすべてのパケットに localhost(127.0.0.1 のフレンドリーネーム)が含まれていることに注目してください。host フィルタは非常に包括的で、指定された IP アドレスがデータを送信したか受信したかに関係なく、パケットをキャプチャします。

もし単一のホストではなく、コンピュータのネットワーク全体を監視する必要がある場合は、host キーワードを net に置き換えることができます(例:net 192.168.1.0/24)。今のところは、単一ホストの探索に集中しましょう。

方向(送信元/宛先)によるフィルタリング

特定のコンピュータが会話に関与していることを知るだけでは不十分な場合があります。郵便局を想像してみてください。ある人が「送信している」手紙だけを見たい場合、彼らが「受信している」手紙は完全に無視したいかもしれません。

送信トラフィックと受信トラフィックは、調査において異なる問いに対する答えとなるため、方向は重要です。送信トラフィックはホストが何に接続しようとしているかを明らかにし、マルウェアのコールバックやデータ流出を追跡する際に役立ちます。受信トラフィックはどのサービスが標的になっているかを明らかにし、サーバーに対するスキャンや攻撃を調査する際に役立ちます。

BPF には、トラフィックの正確な方向を指定するための src(送信元)および dst(宛先)修飾子が用意されています。

フィルタを調整して、127.0.0.1 から発信されたパケットのみをキャプチャするようにしましょう。src 修飾子を以前の host キーワードと組み合わせることで、tcpdump に何を検索すべきかを正確に伝えます。

以下のコマンドを実行してください:

sudo tcpdump -i lo -c 3 src host 127.0.0.1

ヒント:src 127.0.0.1 と書いても動作します(host という単語は省略可能であるため)。しかし、src host と明示的に記述する方が、コマンドが非常に読みやすくなるためベストプラクティスとされています。

出力は以下のようになります:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:20:15.555111 IP localhost.54321 > localhost.http-alt: Flags [P.], seq 1:85, ack 1, win 512, options [nop,nop,TS val 234567 ecr 234567], length 84
10:20:15.555888 IP localhost.http-alt > localhost.54321: Flags [.], ack 85, win 512, options [nop,nop,TS val 234568 ecr 234567], length 0
10:20:16.111222 IP localhost > localhost: ICMP echo request, id 5678, seq 1, length 64
3 packets captured

出力をよく見ると、パケット記述の最初の部分(> 記号の前)が送信元を表しています。内部ループバックインターフェースでキャプチャしているため、両側が localhost と表示されますが、複数のコンピュータにまたがる現実のシナリオでは、src を使用することで、その特定の IP アドレスからの送信トラフィックのみを確実に表示できます。

逆に、受信側として機能し、マシンに到着する受信トラフィックのみを監視したい場合は、単に dst host 127.0.0.1 を使用します。

ポートとプロトコルによるフィルタリング

IP アドレスによるフィルタリングで適切なマシンに到達できますが、現代のサーバーはマルチタスクをこなします。1 台のサーバーが Web サーバー、メールサーバー、セキュアアクセスポイントとして同時に機能している場合があります。これらの異なるサービスは、「ポート」と呼ばれる番号付きの「ドア」を使用することで分離されています。

ポートは物理的なソケットではありません。これらは、オペレーティングシステムが同時に多くの会話を分離するために使用する論理的な番号です。そのため、「同じホスト」であっても「同じアプリケーション」であるとは限りません。1 台のマシンが多くの無関係なネットワーク活動に関与している可能性があるため、ポートフィルタリングは調査対象のサービスを正確に分離するのに役立ちます。

例えば、通常の Web トラフィックはほぼ常にポート 80 を流れます。特定のサービスにズームインして他を無視するには、port キーワードを使用します。

バックグラウンドスクリプトは、ポート 8080 で Web トラフィックを生成しています。tcpdump を設定して、この特定のドアを通過するデータのみをキャプチャしましょう。

以下のコマンドを実行してください:

sudo tcpdump -i lo -c 4 port 8080

出力例:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:25:10.123456 IP localhost.34567 > localhost.http-alt: Flags [S], seq 1122334455, win 65495, options [mss 65495,sackOK,TS val 345678 ecr 0,nop,wscale 7], length 0
10:25:10.123489 IP localhost.http-alt > localhost.34567: Flags [S.], seq 5544332211, ack 1122334456, win 65483, options [mss 65495,sackOK,TS val 345678 ecr 345678,nop,wscale 7], length 0
10:25:10.123501 IP localhost.34567 > localhost.http-alt: Flags [.], ack 1, win 512, options [nop,nop,TS val 345678 ecr 345678], length 0
10:25:10.124111 IP localhost.34567 > localhost.http-alt: Flags [P.], seq 1:85, ack 1, win 512, options [nop,nop,TS val 345679 ecr 345678], length 84
4 packets captured

前のステップで ICMP(ping)パケットが流れていたことを覚えているかもしれません。しかし、この出力にはそれらの兆候は全くありません。port 8080 フィルタは無関係な通信をすべて無視し、Web サービスのみのクリーンなビューを提供しました。

ポートに加えて、tcp、udp、icmp などのキーワードを使用して、プロトコル名を指定することで広範なネットワークプロトコルでフィルタリングすることもできます。これをテストするために、忙しい Web トラフィックを無視して、ICMP(ping)パケットのみをキャプチャしてみましょう。

以下のコマンドを実行してください:

sudo tcpdump -i lo -c 2 icmp

出力例:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:28:05.999111 IP localhost > localhost: ICMP echo request, id 9012, seq 1, length 64
10:28:05.999133 IP localhost > localhost: ICMP echo reply, id 9012, seq 1, length 64
2 packets captured

port やプロトコルのキーワードを使用することで、ノイズを切り分け、調査したいアプリケーションに正確に焦点を合わせることができます。

論理演算子(AND/OR)によるフィルタの組み合わせ

Berkeley Packet Filters を真にマスターするには、複数のルールを組み合わせる方法を学ぶ必要があります。現実の調査は単純なケースばかりではなく、非常に具体的なシナリオを定義する必要があることがよくあります。

ここで、BPF は単なるキーワードのリストではなく、パケットのための小さなクエリ言語のように感じられるようになります。あなたは必要なトラフィックを構造化された論理的な方法で記述しているのです。この考え方は、後のコースで多くのツールに再登場します。SIEM 検索、侵入検知ルール、データベーススタイルのログクエリなどはすべて、広範なデータセットを正確な条件に絞り込むという同じ習慣に基づいています。

BPF では、標準的な論理演算子を使用して条件を結合できます:

  • and(両方のルールが真である必要がある)
  • or(少なくとも 1 つのルールが真である必要がある)
  • not(ルールが明示的に偽である必要がある)

重要なヒント:Linux ターミナルでこれらの論理演算子を使用する場合、BPF 式全体を引用符で囲む(例:"port 80 and tcp")のが非常に良い習慣です。これにより、Linux シェルがフィルタコマンドをシステムコマンドと誤認するのを防ぐことができます。

これを試してみましょう。TCP プロトコルを使用しており、かつ宛先ポート 8080 に向かっているトラフィックのみをキャプチャします。

以下のコマンドを実行してください:

sudo tcpdump -i lo -c 4 "tcp and dst port 8080"

出力例:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:32:15.111222 IP localhost.45678 > localhost.http-alt: Flags [S], seq 2233445566, win 65495, options [mss 65495,sackOK,TS val 456789 ecr 0,nop,wscale 7], length 0
10:32:15.111255 IP localhost.45678 > localhost.http-alt: Flags [.], ack 3344556678, win 512, options [nop,nop,TS val 456789 ecr 456789], length 0
...
4 packets captured

この調整された結果では、localhost.http-alt は > 矢印の右側にのみ表示されており、その特定のポート宛てのパケットのみをキャプチャできたことが証明されています。

最後に、not 演算子を見てみましょう。これは「既知のノイズ」を除外して、未知のものに集中するために非常に役立ちます。ループバックインターフェース上のすべてのトラフィックを監視したいが、ポート 8080 の騒がしい Web トラフィックは除外したいとします。

以下のコマンドを実行してください:

sudo tcpdump -i lo -c 2 "not port 8080"

出力例:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:35:22.333444 IP localhost > localhost: ICMP echo request, id 3456, seq 1, length 64
10:35:22.333466 IP localhost > localhost: ICMP echo reply, id 3456, seq 1, length 64
2 packets captured

tcpdump に対してポート 8080 を結果から除外するように明示的に指示したため、代わりにバックグラウンドで流れている ICMP ping パケットが平和的にキャプチャされました。and、or、not を戦略的に連鎖させることで、ネットワーク上で必要なものを正確に見るための非常に精密なレンズを作り上げることができます。

まとめ

おめでとうございます!あなたは高度なパケットフィルタリングの世界へ足を踏み入れました。

混沌としたネットワークストリームの中から、必要なものを正確に見つけ出す方法を学びました。host キーワードを使用して特定のコンピュータをターゲットにし、src と dst でフローの方向を制御する練習をしました。特定の port とプロトコルをフィルタリングすることで、特定のアプリケーションを分離しました。そして最も重要なこととして、論理演算子(and、or、not)を使用してこれらすべての要素を組み合わせ、外科手術のように正確で非常に具体的な検索を行う方法を学びました。

これらのスキルは不可欠です。不正な接続を追跡するシステム管理者であれ、巧妙な攻撃を追跡するセキュリティアナリストであれ、Berkeley Packet Filters をマスターすれば、ネットワークのノイズに圧倒されることは二度とありません。さまざまな組み合わせを試して、実験を続けてください!