linuxtcの「u32matchip sport 80」を使用すると、ポート80に一致できますが、ポート範囲10000〜20000に一致するにはどうすればよいですか。
マスクを使用することはできますが、難しいです。
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に出てくる方法です。]
「より小さい」と「より大きい」の比較をサポートする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
興味のある人のために@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
ブログでこの簡単なスクリプトを作成して、任意のポート範囲のマスクを作成しました...
間違ったやり方を見つけるためだけにグーグルで検索するのに飽きました...お楽しみください!
http://marcelustrojahn.blogspot.com/2011/06/u32-port-masks_14.htmlサイトがダウンしています:(