同学们好,我有一个问题想跟大家探讨一下,听听你们的想法。
假设说我们需要为某个网络入口设定一个IP白名单规则,仅允许白名单内的IP地址通过。现在我们拿到了这份白名单:
192.168.1.1
192.168.1.2
192.168.1.3
我们可以使用iptables编写3条规则,此时规则检测是线性过程,每一次检查都需要遍历这3条规则。这时候我们发现可以通过IP CIDR的形式来减少规则的数量。例如
192.168.1.0/30
我们只使用了1条规则,就完成了对上述3个IP地址的聚合,减少了规则的数量。不过这里引入了一个新的问题,这个规则对 192.168.1.0 也判定为合法的IP地址了(假设主机号全0和全1允许使用)
现在给予一份IP地址的列表,其中IP地址的分布存在一部分比较稀疏,一部分比较稠密。如果让你设计一个算法,将这些IP地址聚合减少规则的条数,同时尽可能收敛覆盖的空间,你有什么好的办法?这个问题看起来是一个求出最优解的问题,你可以自定义规则条数成本以及覆盖空间的成本。
例子
192.168.1.1
192.168.1.2
方法一:
192.168.1.1/32
192.168.1.2/32
方法二:
192.168.1.0/31
192.168.1.2/31
方法三:
192.168.1.0/30
方法四:
192.168.1.0/29
上面的方法中,方法三和四的规则条数更少。而方法三的规则的覆盖范围更小,因此方法三的规则是较优的。看到这里你可能会想,为什么不用ipset呢?ipset通过使用bitmap或者是hashmap的数据结构以接近O(1)的时间完成IP地址的匹配,并且只需要使用1条规则就能完成对n个IP地址的匹配。
使用ipset搭配iptables的思路很好,但是真不巧,在这个网络入口上我们无法安装ipset。