IPSET of Linux
背景
IPSets 是 Linux 内核的一个框架,可以使用ipset来管理。IPSets 依据 IP 类型以 Hashtable 的方式大量储存 IP地址/网段/端口/MAC地址/网络接口名称,查询十分便捷且迅速。
- 你可以仅用一条iptables来匹配大量的IP地址或端口号。而不用写一堆iptables规则,从而将匹配时间从 O(n) 缩减到了 O(1)。
- 可以在不改动iptables规则的情况下进行对需要匹配的IP地址进行动态增减,对系统性能基本无任何影响。
- 可以用一条iptables规则来快速匹配IP类型的组合,如IP地址与端口的组合,IP地址与MAC的组合,IP地址与网段的组等等。
安装
在Debian下仅用一条命令即可,如下:
1 | :~$ sudo apt-get install ipset |
创建 IPSet 规则
- 创建 IPs 规则
1
2
3
4
5
6:~$ ipset create test hash:ip
:~$ ipset add test 114.114.114.114
:~$ ipset add test 8.8.8.8
:~$ ipset add test 1.1.1.1
:~$ ipset add test 2.2.2.2
:~$ ipset add test 3.3.3.3 - 创建网段规则
1
2
3:~$ ipset create test hash:net
:~$ ipset add test 224.0.0.0/4
:~$ ipset add test 192.168.1.0/24
在 iptables 里引用 IPSet
1 | :~$ iptables -I INPUT --match set --match-set test src --jump DROP |
上面的命令为将数据包的源地属于名为 test
的 IPSets 全部丢掉。
在iptables里用set
模块来启用IPSet。src
代表对数据包的源地址进行匹配,这里也可以用dst
来匹配目标地址。
添加注释
1 | :~$ ipset create test hash:ip comment |
添加匹配计数
1 | :~$ ipset create test hash:ip comment counters |
保存和导入 IPSet 规则
1 | :~$ ipset save -f blacklist |
例子
假设有一万条IP地址需要我们拦截,而使用iptables时只能这样做
1 | iptables -I INPUT --source 1.1.1.1 --jump DROP |
因为iptables的规则是按照顺序进行匹配的,所以每条数据包都需要对这一万条拦截规则进行匹配,而每次的匹配都需要去反复读取数据包的源IP地址,这时时间复杂度为 O(1000),会严重拖累iptables的性能。
而我们现在改为使用ipset来进行匹配,就变成了
1 | ipset create test hash:ip |
可以看到,现在我们只使用了一条iptables 规则,所以此时只需要读取取一次数据包的源IP,然后在IP Sets的哈希表里进行匹配即可,时间复杂度被简化成了 O(1),这对iptables的性能提升十分巨大。
References:
- IP Sets
- Iptabes