web-dev-qa-db-ja.com

u32フィルターを使用してポート範囲を一致させる方法

linuxtcの「u32matchip sport 80」を使用すると、ポート80に一致できますが、ポート範囲10000〜20000に一致するにはどうすればよいですか。

2
Supratik

マスクを使用することはできますが、難しいです。

 u32 match ip sport 4096 0xf000 = sport 4096-8191
 u32 match ip sport 8192 0xe000 = sport 8192-16383

0xf000/0xe000がマスクです。パケットから抽出されたWordは、比較前にこのマスクを使用してビット単位で処理されます。

value = 0001000000000000
mask  = 1111000000000000

start = 0001000000000000
end   = 0001111111111111

また、1つのclassidに対して多くのフィルターを作成できます。

tc filter add dev eth0 parent 1:0 prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 10000 0xffff classid 1:13
tc filter add dev eth0 parent 1:0 prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 10001 0xffff classid 1:13
tc filter add dev eth0 parent 1:0 prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 10002 0xffff classid 1:13

あなたの例では、いくつかの「tcフィルター」を作成する必要があります。

first: sport 10000 0xfff0 (10000-10015)
second: sport 10016 0xffe0 (10016-10047)
.............

等.

10000=10011100010000

0010011100010000
           |
     first not zero
1111111111111111
mask
1111111111110000=0xfff0

[基本的に、範囲の最初の数値(この例では10,000)を取得し、それを2進数(0010011100010000)に変換します。次に、最初の非0ビットに遭遇するまで、この2進数を右から左にスキャンします。次に、そのビットの左側のビットをすべて1を含め、右側のすべてのビットをゼロにします。それがあなたがマスクとして0xfff0に出てくる方法です。]

4
alvosu

「より小さい」と「より大きい」の比較をサポートするu32フィルターの代わりに、ematch(拡張一致)を使用できます。 manページ をご覧ください。

以下は、送信元ポートが70〜90の範囲のパケットに一致します(除く)

tc filter add dev eth0 parent 1:protocol ip prio 1 basic match "cmp(u16 at 0 layer transport gt 70)and cmp(u16 at 0 layer transport lt 90)" flowid 1:3

5
Danny Sade

興味のある人のために@alvosuが説明したことを実行するスクリプトを作成しました。

http://blog.roeften.com/2017/01/mask-calculator.html

現在、範囲の右側にさらに多くのポートが含まれます。

フィドルは http://jsfiddle.net/hp6dfnvg/13/ にあります

厄介なpython実装も:

    import logging
    logging.getLogger().setLevel(logging.DEBUG)


    fp = 20001 # From port
    tp = 25000 # to port
    dev = 'ifb0' # dev to add filter rule to
    flow = '1:10' # flow id to set

    def find_lsm(p,o=1):
        m = o
        i = 1
        while(True):
            if(p & m > 0):
                return m,i
            m = m << 1
            i += 1


    l = 0xffff

    ms = 2
    me = None

    cp = fp
    i = 0
    t = ''
    while(True):
        cm,s = find_lsm(cp)

        if cm >= tp:
            break

        e = cp | cm - 1
        m =  l & (l << s -1)
        logging.info('Range %i - %i, mask %08x', cp, e, m )
        i += 1
        t += "tc filter add dev {} parent 1: prio {} protocol ip u32 match ip protocol 17 0xff match ip dport {} 0x{:0>8x} flowid {}\n".format(dev,i,cp,m,flow)
        cp += cm

    print t
2
Roeften

ブログでこの簡単なスクリプトを作成して、任意のポート範囲のマスクを作成しました...

間違ったやり方を見つけるためだけにグーグルで検索するのに飽きました...お楽しみください!

http://marcelustrojahn.blogspot.com/2011/06/u32-port-masks_14.htmlサイトがダウンしています:(

0