Netgraph ipfwおよびnetflowによる柔軟なトラフィックアカウンティング

こんにちは!



FreeBSD netgraphモジュールのレビューを続けています。

今日、ゲストng_ipfw、ng_one2many、古い友人ng_netflowがいます。

彼らの助けを借りて、特定の条件のトラフィックを計算し、これが実際にどのように使用されるかを確認します。



どんなモジュール?



ng_ipfw.gif






ng_ipfw -IPFWファイアウォールからnetgraphサブシステムにアクセスするためのインターフェースを作成するモジュール。 カーネルにロードされると、モジュールは「ipfw:」という名前でnetgraphサブシステムのスペースにノードを自動的に作成し、単一のインスタンスにのみ存在できます。 Ng_ipfwは任意の番号のフックへの接続を受け入れます。フック番号はipfwルールで指定されます。 モジュールに入る各パケットは、ipfwに戻るときに識別できるように、いくつかのパラメーター(ipfwルール、インターフェース、方向)に従ってタグ付けされます。 ファイアウォールに返されたタグなしパケットは破棄されます。 モジュールは制御メッセージを受信しません。



ng_one2many.gif ng_one2many-複数の接続にパッケージを配布できるモジュール。 1つの「1」フックと多数の「many0」、「many1」、「manyN」への接続を受け入れます。これまでのところ、モジュール内には2つのパケット配布アルゴリズムがあります。



1.「1」に含まれるパケットは、異なる「manyN」(xmit_roundrobin)を介して順に終了します。 「manyN」に含まれるすべてのパケットは「1」になります。

2.「1」に含まれるパケットは、すべて「manyN」(xmit_all)を介した出力コピーです。 「manyN」に含まれるすべてのパケットは「1」になります。 (ng_hubの作業と同様)。



また、アップ/ダウンリンクを決定するアルゴリズム、およびコマンドを使用してリンクをオン/オフにする機能があります。これは特定のタスクに必要です。詳細はman ng_one2manyを参照してください。



Ng_one2manyは制御メッセージを受信します:setconfig、getconfig、getstats、clrstats、getclrstats。 基本的に直感的です。 男の詳細。



ng_holeモジュール-基本的なアクションを実行し、入力されたパケットを考慮して破棄します。



前回のFreeBSD Netgraphトピックで、例としてイーサネットトンネルを使用してng_netgraphモジュールについて書きました





IPFW



FreeBSDで作業しているシステム管理者にipfwについて伝えることは意味がありませんが、 Wikipediaで問題なく読むことができることを知らない人はいます。 ipfwでのipfwとnetgraphの相互作用には、2つのngteeとnetgraphルールがあります。たとえば:



ipfwはnetgraph 10をanyからanyに追加します-ルールに該当するすべてのトラフィックをipfwフックに転送します:ng_ipfwモジュールの10



ipfw anyからanyへのngtee 20 ipの追加-ルールに該当するすべてのトラフィックをipfwフックにコピーします:ng_ipfwモジュールの20



少し数えて



各ユーザーのインターフェースを通過する両方向のトラフィックを計算します。 同時に、サブネット192.168.5.0/24および192.168.10.0/24をレジスタから除外します。これらには空きリソースがあります。 ユーザーは、mpdデーモンによってngXインターフェイスで終了します。



ipfwでは、次のようになります。

ipfw table 1 flush

ipfw table 1 add 192.168.5.0/24

ipfw table 1 add 192.168.10.0/24



ipfw add ngtee 10 ip from not "table(1)" to any in via "ng*"

ipfw add ngtee 10 ip from any to not "table(1)" out via "ng*"







つまり、ipfwにコピーします:netgraphサブシステムの10表1にリストされているネットワークに属さないすべてのトラフィック。



ng_ipfw_netflow.gif グラフを描きましょう。 とても簡単です。



ng_ipfwおよびng_netflowおよびng_ksocketモジュールから単純な構造を作成します。 これは統計のコレクションであるため、データは一方向にのみ処理され、適切な場所に送信されます。



IPFWルールを通過するすべてのトラフィックをng_ipfwにコピーします。ng_ipfwはng_netflowに接続し、ksocketに接続してからnetflowコレクターに接続します。



システムに組み込みます



netflowモジュールを作成し、そのiface0フックをipfw 10フックに接続します。

ngctl mkpeer ipfw:netflow 10 iface0

作成されたnetflowモジュールを「netflow」と呼びます。これは作成アドレス「ipfw:10」にあります

ngctl name ipfw:10 netflow

「netflow:」モジュールにiface0を介して純粋なIPパケットを受信するコマンドを送信します。 (ng_netflowモジュールに関する私の最後のトピックの詳細)

ngctl msg netflow:setdlt {iface = 0 dlt = 12}

ksocketモジュールを作成し、そのinet / dgram / udpフックを「netflow:」エクスポートフックに接続します。

ngctl mkpeer netflow:ksocket export inet / dgram / udp

作成されたモジュール「netflow_socket」を呼び出します

ngctl name netflow:エクスポートnetflow_socket

「netflow_socket」モジュールに、コレクターに接続するコマンドを送信します。

ngctl msg netflow_socket:connect inet / 3.3.3.3:9996



それは簡単に思えます-それは動作しますが、それはそうあるべきではないことが判明しました。 ユーザーインターフェイスを離れ、近隣ユーザーのインターフェイスに入るパッケージは2回カウントされます。 ここでは、たとえば発信トラフィックなどのカウントを停止できますが、ng_one2manyモジュールが役立ちます。



新しいカウント



ng_ipfw_one2many_netflow.gif ng_one2manyはラウンドロビンモードで機能し、デフォルトでこれを行うこともできるため、ng_ipfwとng_netflowの間に挿入できます。



トラフィックを半分に分割するには、one2manyのパケットを配信するための必須条件がアクティブ状態のフックであるため、one2manyをmany0およびmany1フックでng_netflowおよびng_holeに接続する必要があります。



わずかなエラーでパケットの半分のみがアカウンティングに送られ、2番目の部分は破棄されることが判明しました。



2番目のグラフでは、新しいipfwモジュールフック-20を使用します。また、グラフを作成するとき、ノードに新しい名前を付けて、既に作成したグラフと重複しないようにする必要があります。 その作成は類似しており、詳細に説明しません。



その結果、作業用の最終スクリプトを取得します。





完全なnetflowグラフを収集する最初のスクリプト。

#!/bin/sh

case "$1" in

start)

echo "Starting full netflow."

ngctl mkpeer ipfw: netflow 10 iface0

ngctl name ipfw:10 netflow

ngctl msg netflow: setdlt {iface=0 dlt=12}

ngctl mkpeer netflow: ksocket export inet/dgram/udp

ngctl name netflow:export netflow_socket

ngctl msg netflow_socket: connect inet/3.3.3.3:9996

echo "Ok."

exit 0

;;

stop)

echo "Stopping full netflow."

ngctl shutdown netflow_socket:

ngctl shutdown netflow:

echo "Ok."

exit 0

;;

restart)

sh $0 stop

sh $0 start

;;

*)

echo "Usage: `basename $0` { start | stop | restart }"

exit 64

;;

esac









2番目のスクリプトは、トラフィックの半分を計算するグラフを作成します。

#!/bin/sh

case "$1" in

start)

echo "Starting half netflow."

ngctl mkpeer ipfw: one2many 20 one

ngctl name ipfw:20 one2many

ngctl mkpeer one2many: netflow many0 iface0

ngctl name one2many:many0 netflow_half

ngctl mkpeer one2many: hole many1 black

ngctl name one2many:many1 blackhole

ngctl mkpeer netflow_half: ksocket export inet/dgram/udp

ngctl name netflow_half:export netflow_socket_half

ngctl msg netflow_half: setdlt {iface=0 dlt=12}

ngctl msg netflow_socket_half: connect inet/3.3.3.3:9996

echo "Ok."

exit 0

;;

stop)

echo "Stopping half netflow."

ngctl shutdown netflow_socket_half:

ngctl shutdown blackhole:

ngctl shutdown netflow_half:

ngctl shutdown one2many:

echo "Ok."

exit 0

;;

restart)

sh $0 stop

sh $0 start

;;

*)

echo "Usage: `basename $0` { start | stop | restart }"

exit 64

;;

esac









IPFWでは、新しいデザインを取得しています。 2番目のプレートにネットワークを追加し、その間のトラフィックを2倍減らす必要があります。



ipfw table 1 flush

ipfw table 1 add 192.168.5.0/24

ipfw table 1 add 192.168.10.0/24



ipfw table 2 flush

ipfw table 2 add 192.168.50.0/24

ipfw table 2 add 192.168.51.0/24

ipfw table 2 add 192.168.52.0/24

ipfw table 2 add 192.168.53.0/24



ipfw add ngtee 10 ip from not "table(1)" to any in via "ng*"

ipfw add ngtee 10 ip from any to not "table(1)" out via "ng*"



ipfw add ngtee 20 ip from "table(2)" to "table(2)" via "ng*"









それだけです



記事全体を英雄的に読んでくださった皆さんに感謝します。



All Articles