使用IPtables还是使用空路由将一百万个IP地址列入黑名单?


22

我遇到过这样一种情况:客户端需要将一组将近一百万个单独的IP地址(没有子网)列入黑名单,并且网络性能是一个问题。虽然我可以推测IPTables规则对性能的影响比对路由的影响要小,但这只是一个推测。

有没有人有任何确凿的证据或其他理由赞成使用IPTables或空路由作为将IP地址长列表列入黑名单的解决方案?在这种情况下,一切都是自动化的,因此易用性并不是真正的问题。

编辑11年11月26日

经过一些测试和开发,这些选项似乎都不可行。似乎路由查找和iptables都通过规则集进行线性搜索,并且处理这些规则花的时间太长。在现代硬件上,将100万个项目放入iptables黑名单会使服务器的速度降低到每秒约2打数据包。因此IPTables和空路由都消失了。

ipset,如Jimmy Hedman所建议的那样,将非常有用,除了它不允许您在一个集合中跟踪超过65536个地址外,因此,除非有人有任何想法,否则我什至无法尝试使用它。

显然,阻止这么多IP的唯一解决方案是在应用程序层中进行索引查找。不是吗


更多信息:

这种情况下的用例是阻止IP地址的“已知违规者”列表访问Web服务器上的静态内容。FWIW,通过Apache进行阻塞Deny from同样很慢(如果不是更多的话),因为它也进行线性扫描。


仅供参考:最终可行的解决方案是将apache的mod_rewrite与berkeley DB映射结合使用以对黑名单进行查找。伯克利数据库的索引性质使列表可以随着O(log N)性能进行扩展。


5
ipset(ipset.netfilter.org)是否设计得较少以解决此类问题?
Jimmy Hedman

@JimmyHedman:您应该做出一个答案。然后向基准添加建议,以三种方式实现它:)
MikeyB

我很好奇您能否提供更多有关您要解决的问题的信息?也许阻止1M IP地址不是解决问题的方法吗?
SpacemanSpiff

知道为什么要阻止这么多地址以及过滤输入或转发流量会很有帮助。
朱利诺

在这里,您可以看到ipset如何使iptables规则比常规iptables规则快11倍。daemonkeeper.net/781/mass-blocking-ip-addresses-with-ipset希望获得帮助。
外星人托雷斯

Answers:


15

尝试使用iptables并构建多级树以减少查找次数。

iptables -N rules_0_0_0_0_2
iptables -N rules_64_0_0_0_2
iptables -N rules_128_0_0_0_2
iptables -N rules_192_0_0_0_2
iptables -N rules_0_0_0_0_4
iptables -N rules_16_0_0_0_4

iptables -A INPUT -p tcp --dport 80 -s 0.0.0.0/2 -j rules_0_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 64.0.0.0/2 -j rules_64_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 128.0.0.0/4 -j rules_128_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 192.0.0.0/4 -j rules_192_0_0_0_2

iptables -A rules_0_0_0_0_2 -s 0.0.0.0/4 -j rules_0_0_0_0_4
iptables -A rules_0_0_0_0_2 -s 16.0.0.0/4 -j rules_16_0_0_0_4

依此类推-添加嵌套级别;显然,您将需要一种自动的规则构建方式,并且应该为存在一个或多个违规者的网络提供链条-这样,您可以减少必须做的大量查找工作,我认为这可能实际工作。


这听起来确实可行,有效地将防火墙规则查找的时间复杂度从O(n)降低到O(log n),并有效地在iptables中构建了搜索树。
Per von Zweigbergk 2011年

如果您决定走这条路,那么使用某种算法从IP地址列表构建平衡的二进制搜索树,然后将该搜索树的结构作为一组IPtables规则转储,可能会很有用。
Per von Zweigbergk 2011年

@Per von Zweigbergk-的确是……或者只是在不需要进行更深入查找的情况下将树修剪得较早。尽管加载大量规则会花费大量时间。
pQd

这是一个非常好的方法。显然,需要进行一些处理才能维护,但是我认为这是正确的想法。
tylerl 2011年

3
@pQd在iptables等人先前失败之后,我使用带有Berkeley数据库的RewriteMap在apache中实现了一个解决方案。但是我最快的使用iptables的机制在一个循环中每秒加载约100条规则,而iptables-restore在大约4秒内完成了整个设置。这是在顶级台式计算机上。RewriteMap机制对性能的影响很小。
tylerl

11

这正是ipset目的。

从其网站http://ipset.netfilter.org/

如果你想

  • 一口气存储多个IP地址或端口号,并与iptables进行匹配;
  • 针对IP地址或端口动态更新iptables规则,而不会影响性能;
  • 通过一个iptables规则表达复杂的基于IP地址和端口的规则集,并受益于IP集的速度

那么ipset可能是适合您的工具。

它是由netfilter核心团队成员Jozsef Kadlecsik(他也写了REJECT目标)编写的,因此这是我能想到的最佳选择。

它甚至包含在最新的内核中。


据我所知,ipset的IP地址最多为65k。有没有可以处理1M条目的集合类型?
tylerl 2011年

7
如果使用hash:ip设置类型,则可以有大量地址。我尝试了100万次,性能相当不错。如果在检查集合之前设置了-m state --state ESTABLISHED规则,则可以确保仅检查新连接上的集合,这会在处理大量数据包时提高性能。
马修·伊夫,

值得一提的是,具有1M地址的ipset的内存使用量开始变大。根据netfilter邮件列表上的此帖子,当前的2015年ipset哈希大小公式为H * 40byte + (N/4 + N%4) * 4 * element size1.5m插槽哈希中的1M地址约为64MB。使用apache / berkdb解决方案将数据存储在磁盘上,并且仅加载活动地址的页面。
M康拉德

5

我自己尚未对此进行测试,但是当听到您的问题描述时,我立即想到了“ pf”(来自OpenBSD)。

pf地址表的概念可能正是您要寻找的。

根据我所做的一些非常粗略的研究,似乎它具有比更好的扩展潜力ipset。根据PF FAQ关于“运行时选项”的一章,即开即用,无需调整,pf总共支持1000个表,默认情况下,所有表中共有200,000个条目。(如果系统的物理内存小于100MB,则为100,000)。这使我相信,至少值得考虑尝试对其进行测试,以查看它是否可以在任何有用的级别上起作用。

当然,我假设您是在Linux上运行服务器,因此您必须有一个单独的防火墙框,该框运行某些带有pf的操作系统(例如OpenBSD或FreeBSD)。通过完全消除任何类型的有状态数据包筛选,您也许也可以提高吞吐量。


将客户端的服务器体系结构转换为BSD并不是真正的选择。不过,至少要开箱即用。
tylerl 2011年

2
您无需将整个服务器体系结构转换为BSD,只需在实际服务器之前构建一个防火墙就足够了。(足够轻松地在VM中完成。)
Per von Zweigbergk 2011年

2

您是否调查过使用FIB_TRIE而不是FIB_HASH。

FIB_TRIE应该可以更好地扩展您的前缀数量。(/ 32s空路由仍然是前缀,只是非常具体)

您可能需要编译自己的内核才能使用它,但是它会有所帮助。

FIB_TRIE笔记


2

对于后代:根据ipset文档,集合的默认大小为65536,可以通过选项更改。

maxelem该参数对所有哈希类型集的create命令均有效。它确实定义了可以存储在集合中的最大元素数,默认为65536。示例:ipset create test hash:ip maxelem 2048.

由于无法发表评论,因此将其放在此处。


1

对于以后偶然发现此问题的任何人的一些有用的注意事项:

首先,不要分析不需要的任何流量。例如,如果要阻止TCP通信,则仅过滤SYN数据包,这样,每个连接仅需过滤一次。-m state如果需要,可以使用,但是如果性能存在问题,连接跟踪会有其自身的开销,您可能需要避免这些开销。

其次,将一百万条规则放入iptables需要花费很长时间:几分钟。如果您需要跟踪那么多实体,则最好将其排除在netfliter之外。规则集的绝对大小确实有所不同。

第三,目标是避免线性扫描。但不幸的是,iptables和iproute2本质上都是线性的。您可以将规则以二叉树样式划分为大量的链,这限制了您必须查阅的规则数量,但是即使如此,iptables也不太适合这种规模的问题。它将起作用,但是这浪费了宝贵的资源。

第四,也是最重要的是,将工作负载推向用户空间并不是一个坏主意。这使您可以编写自己的严格代码或使用针对您的问题集而调整的现成解决方案。如上所述,我自己针对此问题的解决方案是使用通过apache的mod_rewrite系统触发的BDB查找。这具有额外的好处,即仅在提交有效请求之后,每个会话才触发一次查找。在这种情况下,性能非常快,阻止列表的成本几乎可以忽略不计。

您可以通过将-j QUEUE目标与结合使用iptables进行类似的用户空间操作libnetfilter_queue。该工具功能强大,简单且文档记录不充分。我建议您从可以找到的尽可能多的来源中进行尽可能多的阅读,因为网络上散布着许多有趣的资料,这些资料不属于任何正式文档。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.