これは@stackoverflowでの最初の質問です。
私は一部の VoIP 運用サーバー用の監視ツール、特に Perl の pcap ライブラリを使用して特定のパターンに一致するすべてのトラフィック (VoIP 呼び出し) をキャプチャできるスニフ ツールを作成しています。
「udp」などの貧弱な選択的フィルターを使用して、アプリのコードですべてのフィルタリングを行うことはできません。これは、トラフィックが多すぎて、カーネルがパケット損失の報告に対処できないためです。
次に行うことは、キャプチャ中に可能な限り選択的なフィルターを繰り返し構築することです。最初に、(すべての) SIP シグナリング トラフィックと IP フラグメントのみをキャプチャします (パターン マッチは、どのような場合でもアプリケーション レベルで実行する必要があります)。次に、RTP に関する情報を SIP パケットに見つけたら、「or」句を追加します。特定の IP と PORT を含む実際のフィルター文字列を取得し、setfilter() でフィルターを再設定します。
したがって、基本的には次のようなものです。
初期フィルター : "(udp and port 5060) or (udp and ip[6:2] & 0x1fff != 0)" -> すべての SIP トラフィックと IP フラグメントをキャプチャします
更新されたフィルター: "(udp and port 5060) or (udp and ip[6:2] & 0x1fff != 0) or (host IP and port PORT)" -> 特定の IP、PORT の RTP もキャプチャします
更新されたフィルター: "(udp and port 5060) or (udp and ip[6:2] & 0x1fff != 0) or (host IP and port PORT) or (host IP2 and port PORT2)" -> 2 番目の RTP ストリームをキャプチャします同じように
等々。
監視目的でRTPストリームの「実際の」パケット損失を取得できるため、これは非常にうまく機能しますが、ツールの選択的フィルターバージョンが不十分な場合、いくつかのパケットがあったため、RTPパケット損失率は信頼できませんでしたカーネルによるパケット ドロップが原因で欠落しています。
しかし、このアプローチの欠点に取り掛かりましょう。
キャプチャ中に setfilter() を呼び出すと、関数 set_kernel_filter() のコード コメントで pcap-linux.c (libpcap バージョン 0.9 および 1.1 を確認) に記載されているように、libpcap が「フィルターの変更中に」受信したパケットをドロップするという事実が含まれます。
setfilter() を呼び出すと、一部のパケットが IP フラグメント化されて到着し、一部のフラグメントが失われます。これは、最後に libpcap 統計によって報告されません: トレースを掘り下げているのを見つけました。
これで、このアクションが libpcap によって行われる理由がわかりましたが、私の場合、パケットをドロップする必要はまったくありません (関係のないトラフィックを取得することは気にしません)。
libpcap のコードを変更していないこの問題を解決する方法について何か考えはありますか?