nginx日志的自动封异常ip和解封脚本
设计思路
1.每五分钟统计一次日志异常ip
2.被封的异常ip一小时后自动解封
3.尽量减少对nginx的重启,完成全部判断后再去考虑是否重启nginx进程
4.黑名单ip采用非iptable,使用将deny+ip语句加入blockip.conf中(后期解封比较好处理),并且在上述语句块中nginx.conf中include此文件(blockip.conf可以根据需要放入http 语句块、server 语句块、location 语句块)
5.blockip.conf设计为deny + ip + ;号 + #号 + 时间戳(五个可以分割的值)
程序流程图
程序有两个脚本组成
1.python写的blockip.conf中的ip根据时间戳去解封(简称sub),返回一个是够要重启的信号给shell
2.shell写的根据最近五分钟访问超过100次(生产环境建议改成500-1000)的ip,加入到blockip.conf,根据是否有新ip加入和sub返回值判断nginx是否需要重启
脚本
1.nginx_black.sh
#/bin/bash
#/usr/local/python3.9/bin/python3 /root/ai2/sub_oldip.py
reload1=$(/usr/local/python3.9/bin/python3 /root/ai2/sub_oldip.py) ##调用python脚本,是否返回重启
reload2=nores ##默认值不重启
#echo "$reload1"
sleep 1s
my_log=/root/ai2/log.txt
#logfile=/root
logfile=/usr/local/tengine/logs ##nginx日志
confdir=/usr/local/tengine/conf/blockip.conf ##nginx的blockip.conf目录
time_sjc=$(date -d now +%s) ##获取时间戳
my_log_date=`date +"%y-%m-%d %h:%m:%s"` ##日志记录时间
start_time=`date -d "-5min" +"%h:%m:%s"` ##start_time-stop_time的值为nginx统计日志的时间为5分钟
#echo "$start_time"
stop_time=`date +"%h:%m:%s"`
#echo "$stop_time"
#过滤出单位之间内的日志并统计最高ip数,请替换为你的日志路径
tac $logfile/host.access.log | awk -v st="$start_time" -v et="$stop_time" ' {t=substr($4,rstart+14,21);if(t>=st && t<=et) {print $0}}' |awk '{print $1}' |grep -i -v -e "google|yahoo|baidu|msnbot|feedsky|sogou" |sort | uniq -c | sort -nr |head -20> $logfile/log_ip_top20
ip=`cat $logfile/log_ip_top20 | awk '{if($1>50)print $2}'` ##统计排名前10的ip访问次数,100次以上加入黑名单
ip_tmp=`cat $logfile/log_ip_top20 | awk '{if($1>50)print $2}' |head -1` ##用于if判断去首行,多行会报错
##echo "$ip"
if [ "$ip_tmp" = "" ];then ##如果ip_tmp为空,打印没有黑名单ip
echo "$my_log_date no black ip " >> $my_log
else
# for line in $ip ##按行读取黑名单ip,按格式加入到blockip.conf和日志
# do
# echo "deny $line ; # $time_sjc" >> $confdir
# echo "$my_log_date deny $line " >> $my_log
# done
# #/usr/local/tengine/sbin/nginx -s reload
# reload2=res ##赋值reload2 需要重启
for line in $ip ##按行读取黑名单ip,按格式加入到blockip.conf和日志
do
if [ `grep -c "$line" $confdir` -eq '0' ];then
echo "deny $line ; # $time_sjc" >> $confdir
echo "$my_log_date deny $line " >> $my_log
reload2=res
else
#line_uptime="deny $line ; # $time_sjc"
#sed -e "s/.*'$line'.*$/$line_uptime/g" $confdir
sed -i /"$line"/d "$confdir"
echo "deny $line ; # $time_sjc" >> $confdir
echo "$my_log_date $line is in conf" >> $my_log
fi
done
fi
#echo "$reload1"
#echo "$reload2"
##如果reload1或者reload2都为res则重启,否则不重启;
if [ "$reload1" = "res" ] || [ "$reload2" = "res" ];then
/usr/local/tengine/sbin/nginx -s reload ##替换自己的nginx环境变量
echo "$my_log_date nginx reload" >> $my_log
else
echo "$my_log_date nginx no reload" >> $my_log
fi
2.sub_oldip.py
#!/usr/bin/python3
# chenzhenhua
import string,time,os
time_now = int(time.time())
log_time = time.strftime("%y-%m-%d %h:%m:%s", time.localtime())
dir = "/usr/local/tengine/conf/blockip.conf" ##修改自己的blockip.conf地址
f_log = open("/root/ai2/log.txt","a") ##本程序日志
with open(dir,"r",encoding="utf-8") as f: ##读取blockip.conf
lines = f.readlines()
#print(lines)
with open(dir,"w",encoding="utf-8") as f2: ##把日期小于3600的ip重新写入回blockip.conf
for line in lines:
if line == '' or line == '\n':
continue
else:
old_time = int(line.strip().split()[4]) ##取第五个值,然后和现在时间挫进行对比
time_sjc = time_now -old_time
ipadd = line.split()[1]
if time_sjc > 3600: ###根据要求调整秒数,秒数大于次值不再重新写入blockip.conf
line_log = line.strip().split()[1]
f_log.write("%s sub %s \n"%(log_time,line_log ) )
continue
else:
f2.write(line)
f2.close()
with open(dir,"r",encoding="utf-8") as f3:
lines2 = f3.readlines()
f3.close()
#time.sleep(0.5)
if lines2 == lines: ###对比新、老blockip.conf是否一致
f_log.write("%s py over retrun nores \n" % (log_time))
# time.sleep(0.5)
print('nores') ##返回shell不要求重启
else:
f_log.write("%s py over retrun res \n" % (log_time))
# time.sleep(0.5)
print('res') ##返回shell不要求重启
f_log.close()测试
加入每五分钟执行一次
[root@zabbix ~]# crontab -e */5 * * * * /root/ai2/nginx_black.sh
其他服务器进行ab测试,没有的百度安装
ab -c 10 -n 100 http://172.16.3.89/test2/
再回到本机进行查看,发现已经加入黑名单中
[root@zabbix logs]# tail -f /root/ai2/log.txt 2021-08-14 18:15:02 nginx no reload 2021-08-14 18:20:01 py over retrun nores 2021-08-14 18:20:02 no black ip 2021-08-14 18:20:02 nginx no reload 2021-08-14 18:25:01 py over retrun nores 2021-08-14 18:25:02 no black ip 2021-08-14 18:25:02 nginx no reload 2021-08-14 18:30:01 py over retrun nores 2021-08-14 18:30:02 deny 192.168.200.244 2021-08-14 18:30:02 nginx reload
[root@zabbix logs]# cat /usr/local/tengine/conf/blockip.conf deny 192.168.200.244 ; # 1628937002
我们再去刚才ab测试服务器进行curl查看,已经返回403
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论