项目上线之后,经常会被一些爬虫盯上,这些IP产生大量高频请求,导致带宽流量异常,对服务器造成负荷。针对这种问题可以采用iptables+ipset进行封禁处理。
为什么不单独用iptables?
因为iptables创建大量规则的时候性能会严重下降,性能指数是O(n)。而ipset是一个ip集合,一条iptables规则链接一个ipset,性能指数是O(1),ip集合存储在带索引的数据结构中,这种结构即使集合比较大也可以进行高效的查找。此外,ipset支持动态修改,即使ipset的iptables规则已经启动,新加入到ipset中的IP也能生效。
centos/redhat安装ipset
yum install ipset -y
创建一个ipset
ipset create xxx hash:net (也可以是hash:ip ,这指的是单个ip,xxx是ipset名称)
ipset最大存储数量默认为65536个元素,使用maxelem指定数量
示例:
#集合名字:blacklist,timeout 3600 表示封禁3600s,timeout为0表示永久;
ipset create blacklist hash:ip timeout 3600
#指定最大存储数量
ipset create blacklist hash:ip maxelem 1000000
#添加一个黑名单IP
ipset add blacklist 192.168.10.1
#删除一个黑名单IP
ipset del blacklist 192.168.10.1
#删除一个ipset
ipset destroy blacklist
创建一条iptables规则用来过滤黑名单IP
#添加一条 iptables规则,链接ipset,开启封禁80,443策略
iptables -A INPUT -p tcp -m set --match-set blacklist src -m multiport --dports 443,80 -j DROP
#也可以封禁所有端口
iptables -I INPUT -p tcp -m set --match-set blacklist src -m multiport -j DROP
基于自定义访问频率阈值或者请求敏感关键字来创建自动筛选恶意IP的脚本/data/iptables_ipset_deny.sh
FILES:nginx的access.log文件
sensitive: 敏感关键字
threshold: 一分钟内请求频率阈值
#!/bin/bash
FILES="/data/nginx/logs/access.log"
sensitive="sensitive_word"
threshold=1000
ip_file="/tmp/ip_file"
sensitive_file="/tmp/sensitive_file"
DATE=`date -d '1 minutes ago' +%Y:%H:%M`
grep ${DATE} ${FILES} | awk '{print $1}' | sort | uniq -c | sort -n | tail -n 1 > ${ip_file}
grep ${DATE} ${FILES} | grep -i ${sensitive} | awk '{print $1}' | sort -n | uniq > ${sensitive_file}
ip_file_number=`awk '{print $1}' ${ip_file}`
ip_file_ip=`awk '{print $2}' ${ip_file}`
if [[ $ip_file_number -gt $threshold ]];then
ipset add blacklist ${ip_file_ip} timeout 3600
fi
if [ -s ${sensitive_file} ];then
for sensitive_ip in `cat ${sensitive_file}`
do
ipset add blacklist ${sensitive_ip}
done
fi
---------------------
使用crontab启动脚本
echo "* * * * * bash /data/iptables_ipset_deny.sh" >> /etc/crontab