2011年4月23日土曜日

port mirror on linux

だいぶ以前にここに書いたと思ったら、書いていなかった... のでメモ。
実際に使える例ではないけれど、例えば wlan0 を dummy 0 にミラーするのであれば
root になって長いコマンド。wlan0 からの出ていく方は
# tc qdisc add dev wlan0 root handle 10: prio
# tc filter add dev wlan0 parent 10: prio 10 \
> protocol all u32 match u32 0 0 flowid 10:1 \
> action mirred egress mirror dev dummy0
disc prio を wlan0 の最初 (root) として 10 という ID 割り当て。
その 10 を親として 10番という順番で u32 すべてマッチのフィルタを追加。
結果は 10:1 に流すけど 10:1 という qdisc はないのでデフォルト何もせず。
アクションとして dummy0 にミラーを送出。確認は
# tc qdisc ls dev wlan0
qdisc prio 10: root refcnt 5 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
# tc filter ls dev wlan0 handle 10:
filter parent 10: protocol all pref 10 u32 
filter parent 10: protocol all pref 10 u32 fh 800: ht divisor 1 
filter parent 10: protocol all pref 10 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 10:1 
  match 00000000/00000000 at 0
 action order 1: mirred (Egress Mirror to device dummy0) pipe
  index 1 ref 1 bind 1
wlan0 に入ってくる方は
# tc qdisc add dev wlan0 ingress
# tc filter add dev wlan0 parent ffff: prio 10 \
> protocol all u32 match u32 0 0 flowid ffff:1 \
> action mirred egress mirror dev dummy0
こちら ingress は ID が ffff と決まっている他は、入ってくる方と同じ。確認は
# tc qdisc ls dev wlan0 ingress
qdisc prio 10: root refcnt 5 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc ingress ffff: parent ffff:fff1 ---------------- 
# tc filter ls dev wlan0 handle ffff:
filter protocol all pref 10 u32 
filter protocol all pref 10 u32 fh 800: ht divisor 1 
filter protocol all pref 10 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid ffff:1 
  match 00000000/00000000 at 0
 action order 1: mirred (Egress Mirror to device dummy0) pipe
  index 2 ref 1 bind 1
これで wlan0 を promisc モードにして dummy0 で tcpdump
#  ip link set wlan0 promisc on
# tcpdump -nevxi dummy0
とか。ドキュメントとして iproute-doc にも含まれていないのでソースを
apt-get source iproute
とか
git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
とかで持ってきた $SRC/doc/actions/mirred-usage を参照。iproute 全般はで、以下その mirred-usage の抜粋意訳、中途訳


普通のイーサネットスイッチでのミラーやリダイレクトの違いは u32 フィ
ルタ (classifier) でミラーするフローを選択できること。

mirred アクションの使い方:
    mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME>
        DIRECTION := ingreee か egress
        ACTION    := mirror か redirect
        INDEX は特定のポリシ ID
        DEVICENAME はデバイス名

ACTION - mirror はコピーを指定されたデバイスに送る
ACTION - redirect はパケットを横取りして指定されたデバイスに送る
         (なのでローカルプロセスには渡らない)

* 禁止事項
  A. ループさせない 
      eth0 を eth1 にリダイレクト。更に eth1 を eth0 にリダイレクトなど
  B. IFB デバイスから別の IFB デバイスにリダイレクトしない
      ホストはクラッシュしないけどパケット全てが drop される

  A は再帰によるデバイスキューのロック輻輳。
  B は送信ロック (の輻輳?)


---- サンプル

1. eth0 に入ってくるパケットを eth1 にミラー

       # tc qdisc add dev eth0 ingress
       # tc filter add dev eth0 parent ffff: protocol ip prio 10 u32 \
       >    match u32 0 0 flowid 1:2 action mirred egress mirror dev eth1

   mirror を redirect に変えるとコピーせずオリジナルパケットを eth1
   に送出する


2. lo から eth0 に横取り
   lo の ingress に届く全てのパケットを eth0 にリダイレクト

       # tc qdisc add dev lo ingress
       # tc filter add dev lo parent ffff: protocol ip prio 10 u32 \
       >    match u32 0 0 flowid 1:2 action mirred egress redirect dev eth0

   この設定をしたホストで ping -c 127.0.0.1 としても失敗する。
   eth0 の先に接続したホストで tcpdump してみると...
   XXX
   このフィルタ内 redirect を mirror に置き換えて

       # tc filter add dev lo parent ffff: protocol ip u32 \
       >    match u32 0 0 flowid 1:2 action mirred egress mirror dev eth0

   とすると tc 設定をしたホストと、この eth0 の先にある両方のホスト
   で、パケットを見ることができる。つまりは ping が成功する


3. もうちょっとイカしたサンプル
   lo の ingress にて 10個の内 1個のパケットがランダムに別ホストへ
   --- eth0 へ --- 送る (ランダムは netrand generator を使う)
   XXX: action drop --- 少し違う気がする...

       # tc filter add dev lo parent ffff: protocol ip prio 10 u32 \
       >    match u32 0 0 flowid 1:2 \
       >    action drop random determ ok 10
       >    action mirred egress mirror dev eth0


4. 10.0.0.9 から来て eth0 に出ていくパケット
   (ローカルの IP か forwarding するか)
   が 100Kbps を超えると eth1 にリダイレクト

       # tc qdisc add dev eth0 handle 1:0 root prio
       # tc filter add dev eth0 parent 1:0 protocol ip prio 6 u32 \
       >    match ip src 10.0.0.9/32 flowid 1:16 \
       >    action police rate 100kbit burst 90 ok \
       >    action mirred egress mirror dev eth1

5. もっと面白いサンプルとしてフローを (デフォルト全て drop する)
   dummy デバイスにミラーして tcpdump

   192.168.200.200/32 からのパケットをポリシングして、この送出が
   100Kbps を超えてほしくないとか

       # tc qdisc add dev eth0 handle 1:0 root prio
       # tc filter add dev eth0 pareht 1: protocol ip prio 10 u32 \
       >    match ip src 192.168.200.200/32 flowid 1:2 \
       >    action police rate 100kbit burst 90 drop

   eth0 で tcpdump を実行すると 192.168.200.200/32 からのパケット送
   出がドロップされようと、されまいと全て見ることができる (tcpdump
   は egress される全てのパケットを見せるから)。ルールを少しだけ拡張
   して make out したパケットを見るためには

       # tc qdisc add dev eth0 handler 1:0 root prio
       # tc filter add dev eth0 parent 1: protocol ip prio 10 u32 \
       >    match ip src 192.168.200.200/32 flowid 1:2 \
       >    action police rate 100kbit burst 90 drop \
       >    action mirred egress mirror dev dummy0

   dummy0 で tcpdump を動かして、make out されたパケットだけを見る

       # tcpdump -n -i dummy0 -x -e -t

   mirror を redirect に置き換えると、これらパケットは XXX 一切 make
   out できなくなる

0 件のコメント: