解释说明
支持nginx和httpd的日志格式,直接拿去用就行,用的是centos7环境,依托iptables,没有的需要安装并启动iptables
yum -y install iptables-services; systemctl start iptables
复制代码粘贴到服务器,init方法会自动添加services系统服务,使用systemctl就可以管理
bash 脚本.sh init
systemctl start blacklist
shell代码
#!/bin/bash
:<<!
实现原理:
每隔1分钟执行封禁ip操作:检测日志前1分钟内所有ip的访问次数,大于限制次数就封禁ip,记录封禁ip的时间
执行封禁ip操作后,执行解封操作:找出<=当前时间减去封禁时长的ip地址,解封此ip
!
# 监控日志路径,只支持nginx和httpd的日志格式
WebLog='/var/log/httpd/access_log'
# 封禁ip日志
BlockLog='/var/log/httpd/blacklist.log'
# pid文件目录
PidFile='/tmp/.blacklist.pid'
# 封禁端口(中间逗号隔开,不可有空格)
DropPort=80,443
# 每分钟最大访问量,1分钟内超出则封禁
MaxNum=100
# 封建时长(秒)
BlockTime=600
function Block {
function getIpList {
# 获取1分钟前所有超过访问最大次数的ip
time1m=$(date -d '60 second ago' '+%d/%b/%Y:%T' | sed 's/..$//')
grep "${time1m}" $WebLog |awk '{print $1}'|sort -n|uniq -c|awk '$1>count{print $1"-"$2}' count=$MaxNum
}
function blockIp {
# 封禁传入的ip地址,并写入封禁日志
if [ $(iptables -t filter -nL BLACKLIST | grep $1 &>/dev/null;echo $?) -ne 0 ]
then
block_time=$(date '+%F %T')
block_time_stamp=$(date -d "$block_time" +%s)
iptables -t filter -I BLACKLIST -p tcp -s $1 -m comment --comment "$block_time $block_time_stamp $2" -m multiport --dports $DropPort -j DROP
# echo "$block_time - $1 - $2" | tee $BlockLog
echo "$block_time - $1 - $2" >> $BlockLog
echo "BlockIp: $1 - $2"
fi
}
for i in $(getIpList)
do
arr=(`echo $i|tr '-' ' '`)
blockIp ${arr[1]} ${arr[0]}
done
}
function UnBlock {
function getIdList {
# 获得需要解禁的iptables的链号,从大到小排序
time_stamp=$(date -d "$(date -d "$BlockTime second ago")" +%s)
iptables -t filter -nL BLACKLIST --line-numbers| sed "1,2d" | sort -nr | awk '$10<=stamp{print $1}' stamp=$time_stamp
}
for i in $(getIdList)
do
iptables -t filter -D BLACKLIST $i
done
}
function Contrl {
function start {
# 创建pid文件
echo $$ > $PidFile
# 创建iptables链
iptables -t filter -N BLACKLIST
iptables -t filter -I INPUT -p tcp -j BLACKLIST
while :
do
Block
UnBlock
sleep 60
done
}
function stop {
# 杀死进程 删除进程pid文件
kill $(cat $PidFile) &> /dev/null
rm -rf $PidFile
# 清空并删除iptables链
iptables -t filter -F BLACKLIST
iptables -t filter -D INPUT -p tcp -j BLACKLIST
iptables -t filter -X BLACKLIST
}
case $1 in
init)
echo -e "[Unit]\nDescription=blacklist service\nAfter=iptables.service\nRequires=iptables.service\n\n[Service]\nExecStart=/bin/bash $(pwd)/$0 start\nExecReload=/bin/bash $(pwd)/$0 restart\nExecStop=/bin/bash $(pwd)/$0 stop\nPIDFile=${PidFile}\n\n[Install]\nWantedBy=multi-user.target" > /usr/lib/systemd/system/blacklist.service
;;
start)
[ ! -f $WebLog ] && echo -e "\033[1;31mCan not find file:'$WebLog' \033[0m" && exit 1
[ -f $PidFile ] && [ $(ps -ef | grep $(cat $PidFile) | grep -v 'grep' &> /dev/null ; echo $?) -eq 0 ] && echo -e "\033[1;31mProcess already exists. pid:`cat $PidFile` \033[0m" && exit 2
start
;;
stop)
stop
;;
restart)
stop
start
;;
esac
}
Contrl $1