如何使用 u32 过滤器匹配端口范围

如何使用 u32 过滤器匹配端口范围

在 Linux tc 中使用“u32 match ip sport 80”我可以匹配端口 80,但是如何匹配端口范围 10000 - 20000?

答案1

可以使用面膜,但是比较困难:

 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 过滤器”:

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

ETC。

10000=10011100010000

0010011100010000
           |
     first not zero
1111111111111111
mask
1111111111110000=0xfff0

[基本上,取范围内的第一个数字(本例中为 10,000)并将其转换为二进制( 0010011100010000 );然后从右到左扫描这个二进制数,直到遇到第一个非 0 位;然后将该位左侧的位全部设为 1(包括 1),将其右侧的所有位设为 0。这就是您得到 0xfff0 作为掩码的方法。]

答案2

您可以使用 ematch(扩展匹配)代替 u32 过滤器,它支持“小于”和“大于”比较。请查看手册页

以下匹配源端口在 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

答案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

答案4

我在我的博客上创建了这个简单的脚本来为任何端口范围创建掩码......

我已经厌倦了通过谷歌搜索却发现错误的方法...尽情享受吧!

http://marcelustrojahn.blogspot.com/2011/06/u32-port-masks_14.html 网站已关闭 :(

相关内容