iptables 多端口模块是否比多个单独的规则提供更高的性能优势?

iptables 多端口模块是否比多个单独的规则提供更高的性能优势?

多端口模块是否iptables比多个单独的规则提供性能优势?换句话说,是这样的:

iptables -A INPUT -p tcp -m multiport --sports 1,2,3,4,5,6,7,8,9,10,11,12,13,14,80 -j ACCEPT

..比这更有效:

iptables -A INPUT -p tcp --sport 1 -j ACCEPT
iptables -A INPUT -p tcp --sport 2 -j ACCEPT
iptables -A INPUT -p tcp --sport 3 -j ACCEPT
iptables -A INPUT -p tcp --sport 4 -j ACCEPT
iptables -A INPUT -p tcp --sport 5 -j ACCEPT
iptables -A INPUT -p tcp --sport 6 -j ACCEPT
iptables -A INPUT -p tcp --sport 7 -j ACCEPT
iptables -A INPUT -p tcp --sport 8 -j ACCEPT
iptables -A INPUT -p tcp --sport 9 -j ACCEPT
iptables -A INPUT -p tcp --sport 10 -j ACCEPT
iptables -A INPUT -p tcp --sport 11 -j ACCEPT
iptables -A INPUT -p tcp --sport 12 -j ACCEPT
iptables -A INPUT -p tcp --sport 13 -j ACCEPT
iptables -A INPUT -p tcp --sport 14 -j ACCEPT
iptables -A INPUT -p tcp --sport 80 -j ACCEPT

在第一种情况下,每个包都会检查tcpmultiport模块,但只有一条规则。在第二种情况下,为每个包检查 15 条规则,但对于每个规则,仅tcp处理模块。

我做了一个简单的网络拓扑如下:

server1[eth2] <--> [enp0s31f6]server2

eth2in和in都是1GigE网络适配器server1,并通过5m Cat5e电缆连接。当我在没有任何防火墙规则的情况下从到下载 10000 MiB 文件时,吞吐量为 942Mbps。然后我生成了 4369 个这样的规则:enp0s31f6server2server1server2

for i in {1..65535}; do if ((i%15 == 0)); then iptables -A INPUT -p tcp -m multiport --sports $p$i -j ACCEPT; p=; else p=$p$i,; fi; done

这意味着有 4369 条multiport规则,每条规则有 15 个端口。例如:

# iptables -L INPUT 1 -v -n --line-numbers 
1        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport sports 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
# iptables -L INPUT 4369 -v -n --line-numbers 
4369     0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport sports 65521,65522,65523,65524,65525,65526,65527,65528,65529,65530,65531,65532,65533,65534,65535
# 

现在,当我执行wget --report-speed=bits -4 -O /dev/null 10.10.10.1:65535in时server2,令我惊讶的是,吞吐量仍然是 942Mbps。下一步,我刷新了INPUT链并生成了 65535 条规则,如下所示:

for i in {1..65535}; do iptables -A INPUT -p tcp --sport $i -j ACCEPT; done

我再次执行,wget --report-speed=bits -4 -O /dev/null 10.10.10.1:65535现在server2吞吐量下降到 580Mbps。那么,在极端情况下,这种multiport方法更有效,我这样说对吗?然而,在没有数万条规则或数十Gbps流量的正常情况下,没有实际区别吗?

答案1

iptables 遍历表中的每条规则,直到找到与终止目标的匹配项,因此规则越少意味着 CPU 使用率越低。尽管有些规则比其他规则运行得更快,例如多端口15 个端口的规则可能比同等端口的规则更快规则(就像 Hauke Laging 的回答)。因此,不仅规则的数量很重要,而且规则的类型也很重要。

源代码为TCP/UDP,多端口匹配扩展提供了一些经验法则,但是因为很难预测哪里进展缓慢,我建议对可能的 iptables 规则集进行基准测试,看看哪一个更快。例如我跑iperf3仅包含 3 个端口的列表,并且传输控制协议模块比多端口提供类似吞吐量的模块。

如果您仍然热衷于微基准测试,我计算了运行该程序所需的 CPU 周期ipt_do_table使用这个非常非常基本的内核函数系统点击脚本:

global call_cycles = 0

probe kernel.function("ipt_do_table@net/ipv4/netfilter/ip_tables.c").call {
    call_cycles = get_cycles()
}

probe kernel.function("ipt_do_table@net/ipv4/netfilter/ip_tables.c").return {
    delta = get_cycles() - call_cycles
    printf(" <- delta = %d\n", delta)
}

以下是我在运行 Linux 4.15 的虚拟机上遍历所有规则的数据包的结果:

模块 港口 规则 运行1 运行2 运行3 运行4 运行5
传输控制协议 4500 4500 973148 1032564 856528 410894 854708
多端口 4500 300 89370 259250 99752 225275 182256
4500 1 28463 43494 28315 33589 40988

答案2

我不知道,Linux 如何在操作码级别处理 Netfilter 规则。但多端口方法可以通过一次操作执行多项检查。

由于 1Gb/s 对于 CPU(即使是慢速 CPU)来说也不算多,因此您需要极端情况也就不足为奇了。但两种方法即使在相同的吞吐量下也可能产生完全不同的负载。由于这是内核内容,因此可能没有在/proc/loadavg.因此,您必须在同一系统上运行 CPU 密集型应用程序并测量其性能才能看到真正的差异。

但我认为您的比较有点不公平,因为多端口检查一次,-p tcp而多规则则执行相同的检查 65536 次。因此你会这样做:

iptables -N tcp_ports
iptables -A INPUT -p tcp -j tcp_ports
for ((i=1;i<65536;i++)); do iptables -A tcp_ports --sport $i ...

我只是意识到你不能忽略 TCP 检查,因为它是--dport.但这是多规则方法速度较慢的原因之一。

我不确定多端口是否适用于像您这样的情况。ipset创建了巨大的比较列表。所以这可能就是您真正想要的。

ipset create foo bitmap:port range tcp:10000-19999
ipset add foo tcp:10000-19999
iptables -A INPUT -p tcp -m set --match-set foo dst

相关内容