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
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论