Назад | Перейти на главную страницу

Как сопоставить диапазон портов с помощью фильтра u32

с помощью "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 сайт не работает :(