利用 ipset 封禁大量 IP
环境:CentOS7.4 自带6.29 版本(目前全球服务器厂商普遍使用的CentOS 最高版本为 7.4)
用途:当机器受到网络***时,使用 iptables 封 IP,有时候可能会封禁成千上万个 IP,如果添加成千上万条规则,在一台注重性能的服务器或者本身性能就很差的设备上就不在适用了。ipset 就是为了避免这个问题而生的。
基本流程:
ipset create test hash:ip
iptables -I INPUT -m set --match-set test src -j DROP
ipset add test 192.168.80.100
ipset add test 192.168.80.101
ipset add test ...
ipset list test # 查看 test 集合的内容
第一步:新建ipset 集合
第二歩:添加iptables 规则
第三步:向ipset中添加ip
创建集合
ipset n,create [ SETNAME ] [ TYPENAME ] [ CREATE-OPTIONS ]
SETNAME:即所创建集合的名字
TYPENAME:即类型名字,用类型来储存ip
CREATE-OPTIONS:即创建选项,TYPENAME类型所对应的值
注意:
TYPENAME相关类型有:bitmap link hash
其中bitmap link 的储存方式的集合大小是固定,hash类型的储存大小是可变的(后面会解释的)
CREATE-OPTIONS相关类型有:ip, net, mac, port, iface
即除了ip外,还可以是网络段,端口号(支持指定 TCP/UDP 协议),mac 地址,网络接口名称,或者多种。
添加iptables 规则
在iptables中可以使用 -m set启用ipset模块
iptables -I INPUT -m set --match-set test src -j DROP
iptables -I INPUT -m set ! --match-set file src -j DROP
如果源地址(src)属于 test 这个集合,就进行 DROP 操作。这条命令中,test 是作为黑名单的,如果要把某个集合作为白名单,添加一个 ‘!’符号就可以。
向集合中添加记录
inset add [ SETNAME ] [ ADD-ENTRY ] [ ADD-OPTIONS ]
SETNAME:即所要添加ip的集合名字
ADD-ENTRY:所要添加的ip或含端口号等其他类型
ADD-OPTIONS:添加ip时的其他条件(后面会解释的)
ipset add test 4.5.6.7
注意:可以同过以下方法找到需要封禁的ip
netstat -ntu | tail -n +3 | awk '{print $5}' | sort | uniq -c | sort -nr
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
注意:如果创建集合是指定的存储内容包含 ip, 例如 hash:ip 或 hash:ip,port ,在添加记录时,可以填 IP 段,但是仍然是以单独一个个 IP 的方式来存储的
删除
删除集合内的ip
inset del SETNAME DEL-ENTRY
参考添加的解释
ipset del test 192.168.80.100 # 从 test 集合中删除内容
删除集合
ipset destroy test # 删除 test 集合
ipset destroy # 删除所有集合
注意:在删除集合时,如果该集合被iptables规则已经引用,则需先删除集合所在的规则,在删除集合,如果集中存在ip并不会影响删除集合
存储类型
hash:net
hash:net 指定了可以往file 这个集合里添加 IP 段或 IP 地址。
ipset create file hash:net
ipset add file 192.168.80.0/24
ipset add file 192.168.80.0/30 nomatch
ipset add file 192.168.80.9
ipset test file 192.168.80.2
第一条命令:创建hash:net集合
第二条命令:添加192.168.80.0/24该ip段的范围
第三条命令:添加192.168.80.0/30该ip段的范围,nomatch 是之前提到的[ ADD-OPTIONS ],就是添加某ip的附加条件
作用:是把 192.168.80.0/30 从 192.168.80.0/24 这一范围相对更大的IP段里“剥离”出来
也就是说执行完ipset add file 192.168.80.0/24之后,192.168.80.0/24 这一段 IP 是属于file 集合的,接着又执行了 ipset add file 192.168.80.0/30 nomatch 之后,192.168.80.0/24 里包含着的 192.168.80.0/30 这部分,就不属于file 集合了。执行 ipset test file 192.168.80.2就会得到结果192.168.80.2 is NOT in set file,即表示该ip不属于file集合了
注意:如下图所示,即使结果出现了192.168.80.2 is NOT in set file,但还是可以添加到file集合中的,所以在添加IP段的时候,要清楚IP段所表示的范围
hash:ip,port
ipset create pro hash:ip,port
ipset add pro 192.168.80.106,80
ipset add pro 192.168.80.108,udp:53
ipset add pro 192.168.80.104,80-86
第一条:创建 hash:ip,port 集合
第二条:添加 IP 地址为192.168.80.106端口号为80的记录,没有注明协议,默为TCP协议
第三条:注明协议为UDP协议
第四条:注明了IP地址和一个端口号范围,这也是合法的命令
需要注意的是,前面有说过的:如果创建集合是指定的存储内容包含 ip, 例如 hash:ip 或 hash:ip,port ,在添加记录时,可以填 IP 段,但是仍然是以单独一个个 IP 的方式来存储的
解封
创建
如果一个集合是作为黑名单使用,可以通过timeout参数,实现到期自动从黑名单里删除记录
ipset create time hash:ip timeout 300
ipset add time 192.168.80.103
ipset add time 192.168.80.105 timeout 60
第一条:创建一个含有timeout参数的time集合,默认值为1000s
第二条:在添加IP时不加timeout参数时,默认timeout 时间就时1000s
第三条:向集合添加IP 时指定了不同于默认值的 timeout 数值 100,那么这一条记录就会在100s后自动删除
当我们再次查看time集合时,可以看到时间在倒计时,标志着它们在多少秒之后会被删除
修改
如果要重新为某条记录指定 timeout 参数,可以使用 -exit 参数
ipset -exist add time 192.168.80.103 timeout 500
这样192.168.80.103 这一条数据的timeout 值就变成了500
注意:
1. 如果在创建集合时没有指定timeout,那么之后添加记录时不支持timeout 参数,但如果在集合没有指定timeout时,在添加记录时使用了timeout参数,会报出错误想
2. 如果需要默认记录不会过期(自动删除),又需要添加某条记录时加timeout参数,可以在创建集合时指定timeout的值为0
如下图所示:
ipset create err hash:ip
ipset add err 192.168.80.107 timeout 100
# 报错信息为:ipset v6.29: Kernel error received: Unknown error -1
hash的自增
前面说过:bitmap link 的储存方式的集合大小是固定,hash类型的储存大小是可变的
下面介绍下hash的两个参数
hashsize:指定了创建集合时初始大小
maxelem:指定了集合最大存储记录的数量
如下图所示:
ipset create initia hash:ip,port hashsize 4096 maxelem 1000000
ipset add initia 192.168.80.109
这样就创建了一个 initia 集合,初始 hash 大小是 2048,如果满了 hash 会自动扩容为之前的两倍,最大能存储的数量是 100000 个
注意:如果没有指定,则hashsize的默认初始值为1024,maxelem的默认最大值为65536
其他常用命令(包括前面提到的删除)
ipset del test x.x.x.x # 从 test 集合中删除内容
ipset list test # 查看 test 集合内容
ipset list # 查看所有集合的内容
ipset flush test # 清空 test 集合
ipset flush # 清空所有集合
ipset destroy test # 销毁 test 集合
ipset destroy # 销毁所有集合
ipset save test # 输出 test 集合内容到标准输出
ipset save # 输出所有集合内容到标准输出
ipset restore # 根据输入内容恢复集合内容
转载于:https://blog.51cto.com/12384628/2318011