需求说明:
在平常运维工做中,为了防止一些恶意访问的行为,例如不断的请求刷流量,经过实时过滤Nginx访问日志,将单位时间内访问次数达到指定阀值的来源ip查找出来,并经过邮件报警方式及时通知运维人员!html
好比针对url为http://192.168.10.202:8888的访问进行监控,当在1分钟内访问次数超过300次数,就邮件报警给运维人员。
1)nginx日志监控脚本python
[root@Fastdfs_storage_s1 ~]# cat /opt/nginx_log_monit.sh #!/bin/bash #日志文件 logfile=/usr/local/nginx/logs/access.log #开始时间 start_time=`date -d"$last_minutes minutes ago" +"%H:%M:%S"` #结束时间 stop_time=`date +"%H:%M:%S"` #过滤出单位之间内的日志并统计最高ip数 tac $logfile | 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}' | sort | uniq -c | sort -nr > /root/log_ip_top10 ip_top=`cat /root/log_ip_top10 | head -1 | awk '{print $1}'` # 单位时间[1分钟]内单ip访问次数超过300次,则触发邮件报警 if [[ $ip_top -gt 300 ]];then /usr/bin/python /opt/send_mail.py & fi
2)python报警脚本nginx
[root@Fastdfs_storage_s1 ~]# cat /opt/send_mail.py # -*- coding: utf-8 -*- from email import encoders from email.header import Header from email.mime.text import MIMEText from email.utils import parseaddr, formataddr from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from datetime import datetime import os import smtplib def _format_addr(s): name, addr = parseaddr(s) return formataddr((Header(name, 'utf-8').encode(), addr)) # 邮箱定义 smtp_server = 'smtp.kevin.com' smtp_port = 465 from_addr = 'monit@kevin.com' password = os.environ.get('monit@123') to_addr = ['wangshibo@kevin.com'] # 邮件对象 msg = MIMEMultipart() msg['From'] = _format_addr('发件人 <%s>' % from_addr) msg['To'] = _format_addr('收件人 <%s>' % to_addr) msg['Subject'] = Header('Warning:单ip请求次数异常', 'utf-8').encode() # 获取系统中要发送的文本内容 with open('/root/log_ip_top10', 'r') as f: line = f.readline().strip() line = line.split(" ") print(line) # 邮件正文是MIMEText: html = '<html><body><h2>一分钟内单ip请求次数超过阀值</h2>' + \ '<p>ip:%s 请求次数/min:%s</p>' % (line[1],line[0]) + \ '</body></html>' msg.attach(MIMEText(html, 'html', 'utf-8')) server = smtplib.SMTP_SSL(smtp_server, smtp_port) server.login(from_addr, password) server.sendmail(from_addr, to_addr, msg.as_string()) server.quit()
3)写个测试脚本不停curl请求资源触发报警bash
[root@Fastdfs_storage_s1 ~]# cat /opt/curl.sh #!/bin/bash #example:curl.sh http://www.kevin.com 100 usage() { echo "usage: `basename $0` url count" } if [ $# -ne 2 ]; then usage exit 1 fi for i in `seq 1 $2`;do http_code=`curl -o /dev/null -s -w %{http_code} $1` echo $1 $http_code done 手动执行测试脚本 [root@Fastdfs_storage_s1 ~]# /bin/bash /opt/curl.sh http://192.168.10.202:8888 300 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 http://192.168.10.202:8888 200 ...........
4)定时任务,因为上面脚本是监控一分钟内的日志,所以每分钟执行一次运维
[root@Fastdfs_storage_s1 ~]# crontab -e * * * * * /bin/bash -x /opt/nginx_log_monit.sh >/dev/null 2>&1
这里仅仅是实现了邮件告警功能,实际上还能够实现自动屏蔽恶意访问的ip。
能够经过Nginx deny来实现,也能够经过iptables屏蔽("iptables -I INPUT -s x.x.x.x -j DROP"方式)。curl