iptables封掉少量ip处理是没什么问题的,但是当有大量ip攻击的时候性能就跟不上了,iptables是O(N)的性能。而ipset就像一个集合,把需要封闭的ip地址放入这个集合中,ipset 是O(1)的性能,用的hash方式所以特别快。

一、软件及安装

    1、iptables(一般linux都已经安装好的)

    2、ipset:

            ubuntu:apt-get install ipset

二、ipset的使用

    1、查看ip集的列表信息

    ipset list

    2、创建ip集

    ipset create XXXX hash:ip maxelem 100000 timeout 3600

            XXXX:ip集的名字

            hash:ip :为指定类型,还有其他好些类型,比如hash:net,hash:net,net等,具体可以man ipset

            100000:为最大保存ip的数量 

            timeout: 为封闭ip的默认时间,这个参数可以不写,这样就永不解封,除非手动解封

    3、增加ip地址到ip集

    ipset add xxxx 1.1.1.1

    增加网段

    ipset add xxxx 1.1.1.0/24

    4、删除指定的ip或网段

    ipset del xxxx 1.1.1.1
    ipset del xxxx 1.1.1.0/24


    5、保存ip集到文件

   

 ipset save xxxx>ipset_list.txt

    6、还原ip集

    ipset restore <ipset_list.txt

三、自动封禁和解封

    1、创建ip集

    ipset create forbidip hash:ip timeout 172800

    2、创建iptables条目

    iptables -A INPUT -p tcp -m set --match-set forbidip src -m multiport --dports 443,80 -j DROP

或者

  

 iptables -A INPUT -p tcp -m set --match-set forbidip src -m multiport -j DROP


    3、根据条件判断需要封闭的ip

    条件:在上一分钟的nginx的请求中,单一ip请求数超过1000及request_uri中包含passwd字符串的ip都直接封禁,1小时后自动解禁。脚本如下

#!/bin/bash
FILES="/data/nginx_log/xxxxx/access.log"
DATE=`date -d '1 minutes ago' +%Y:%H:%M`
grep ${DATE} ${FILES}|awk -F'|' '{print $3}'|sort -n|uniq -c |sort -nr|head -1>/tmp/ips
grep ${DATE} ${FILES}|grep -i passwd|awk -F'|' '{print $3}'|sort -n|uniq>/tmp/ippwd
NUM=`awk '{print $1}' /tmp/ips`
IP=`awk '{print $2}' /tmp/ips`
IP2=`cat /tmp/ippwd`
threshold=1000
if [[ $NUM -gt $threshold ]];then
/sbin/ipset -! add forbidip $IP timeout 3600
fi
if [ -s /tmp/ippwd ];then
for i in $IP2
do
/sbin/ipset -! add forbidip $i
done
fi

4、脚本自动运行

在crontab中添加此脚本的自动运行

*/1 * * * * bash /path/to/script.sh