IPTables + Limit 模块:为什么 limit-burst 没有得到完全使用?

IPTables + Limit 模块:为什么 limit-burst 没有得到完全使用?

长期读者,第一次发帖。等等等等。

无论如何,我希望有人具有丰富的 iptables/netfilter LIMIT 或 HASHLIMIT 模块经验,并可以解释我所见证的行为。

背景: 我们有一个 Web 服务器,想要限制客户在一个月内可以建立的连接数(顺便说一下,HTTP keepalive 已关闭)。因此,我尝试使用 iptables LIMIT 模块将新连接数限制为每月固定数量(假设为 500)。iptables LIMIT 模块使用“令牌桶”算法,因此我应该能够将限制突发(桶大小)设置为 500,将限制(重新填充率)设置为 500 除以 28 天或大约 18/天。这将确保如果桶每次都完全清空,则在一个月内(4 周)重新填充桶。(我知道这实际上将允许超过 500 个,但它应该足以满足我们的需求)。

这是我的 iptables 规则(我们使用 ipset 对 IP 进行分组。LimBurTest4 包含我的源测试机器)

Chain INPUT (policy DROP 2316 packets, 186K bytes)
 pkts bytes target     prot opt in     out     source               destination
2952K  626M ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0      state RELATED,ESTABLISHED /* Accept outgoing return traffic */
  379 13702 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0      icmptype 8 state NEW limit: avg 1/sec burst 1
  377 30868 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0      tcp flags:0x3F/0x00 /* Block NULL packets */
   73 14728 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0      tcp flags:!0x17/0x02 state NEW /* Block SYN flood */
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0      tcp flags:0x3F/0x3F /* Block XMAS packets */
   24   120 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0      match-set LimBurTest4 src tcp dpt:443 limit: avg 18/day burst 500 /* LimitBurst Test */
   76 30180 LOG        tcp  --  *      *       0.0.0.0/0            0.0.0.0/0      match-set LimBurTest4 src tcp dpt:443 /* LimitBurst Testing */ LOG flags 0 level 4 prefix "LimBurTest Over Quota "
 2522  138K REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443 /* Reject queries */ reject-with tcp-reset

我添加如下 LIMIT 规则:

iptables -I INPUT 7 -m set --match-set LimBurTest4 src -p tcp --dport 443 -m limit --limit 18/day --limit-burst 500 -m comment --comment "Limit Burst Test" -j ACCEPT

测试: 然后我创建了一个简单的 shell 脚本,使用 curl 向我的 Web 服务器一个接一个地发出请求。每次成功的请求大约需要 0.20 毫秒。脚本的输出如下所示:

./limBurTest.sh
1  - 200   -  0.257 ms 
2  - 200   -  0.193 ms 
3  - 200   -  0.155 ms 
etc.
etc.

结果: 我期望此配置能够快速(在几秒钟内)用完所有 500 个连接,然后我才会开始看到被拒绝的连接。然而,这根本没有发生。相反,我的测试脚本成功建立了 24 个连接,其余的都被拒绝了。例如,在上面的 iptables 输出中,我循环运行了 100 次 shell 脚本,您可以在 ACCEPT 规则之后看到 24 个 ACCEPT 规则匹配和 76 个 LOG 规则匹配。我已经在 CentOS 6.8 和 Ubuntu 16.04 上测试过,两者都是这样的行为,但这似乎与文档相反。为什么我不能用完 limit-burst 指定的所有 500 个连接?

是的,当然,我已经进行了大量 Google 搜索,看到很多人说 LIMIT 模块应该完全按照我描述的方式工作。而且我已经多次阅读了 netfilter 文档。

我在这里遗漏了什么?

先感谢您。

答案1

限制模块不是根据连接数进行限制,而是根据 IP 数据包(甚至是巨型数据包)的数量进行限制。因此,如果单个连接大约需要 20.8 个数据包,那么您将看到连接激增500/20.8~=24

有关更多信息,请参阅命令的输出man 8 iptables-extensions|grep -e '^ *limit$' -A 18,特别是短语“最大初始数量数据包匹配: [...]”。

答案2

从 user3338098 开始,为了修复它,你只需要通过添加来匹配 SYN 数据包-m state --state NEW

相关内容