с помощью "u32 match ip sport 80" в Linux tc я могу сопоставить порт 80, но как я могу сопоставить диапазон портов от 10000 до 20000?
Вы можете использовать расширенное совпадение ematch вместо фильтра u32, который поддерживает сравнения «меньше» и «больше». Взгляните на страница руководства.
Следующее соответствует пакетам с портом источника в диапазоне 70-90 (исключая)
tc filter add dev eth0 parent 1: протокол ip prio 1, базовое совпадение "cmp (u16 на транспортном уровне 0 gt 70) и cmp (u16 на транспортном уровне 0 уровня lt 90)" flowid 1: 3
Можно использовать маску, но это сложно:
u32 match ip sport 4096 0xf000 = sport 4096-8191
u32 match ip sport 8192 0xe000 = sport 8192-16383
0xf000 / 0xe000 - это маска. Слово, извлеченное из пакета, перед сравнением проходит побитно с этой маской.
value = 0001000000000000
mask = 1111000000000000
start = 0001000000000000
end = 0001111111111111
Также вы можете создать несколько фильтров для одного 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 filter:
first: sport 10000 0xfff0 (10000-10015)
second: sport 10016 0xffe0 (10016-10047)
.............
и т.п.
10000=10011100010000
0010011100010000
|
first not zero
1111111111111111
mask
1111111111110000=0xfff0
[В основном возьмите первое число в диапазоне (в этом примере 10 000) и преобразуйте его в двоичное (0010011100010000); затем просканируйте это двоичное число справа налево, пока не встретите 1-й бит, отличный от 0; затем превратите все биты слева от этого бита в 1 включительно, а все биты справа от него - в нули. Вот как вы попадаете в 0xfff0 в качестве маски.]
Я сделал сценарий, чтобы сделать то, что @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 сайт не работает :(