Nginx日志實現訪問異常報警詳解
更新時間:2017年03月04日 10:45:49 作者:LoyaChen
Nginx把遇到的不同級別的問題信息寫到錯誤日志。error_log 指令配置記錄到特定的文件,stderr,或者syslog,配置寫到日志的最低級別信息。下面這篇文章主要介紹了利用Nginx日志實現訪問異常報警的相關資料,需要的朋友可以參考下。
前言
在工作中為了防止一些惡意訪問的行為,例如不斷的請求刷流量,通過實時過濾Nginx訪問日志,將單位時間內訪問次數達到指定閥值的來源ip及時的通知系統管理員,這里通過郵件的方式通知。
監(jiān)控腳本
vim /opt/nginx/sbin/nginx_log_monitor.sh
#!/bin/bash
#日志文件
logfile=/opt/nginx/logs/www
#開始時間
start_time=`date -d"$last_minutes minutes ago" +"%H:%M:%S"`
#結束時間
stop_time=`date +"%H:%M:%S"`
#過濾出單位之間內的日志并統計最高ip數
tac $logfile/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}' | sort | uniq -c | sort -nr > $logfile/log_ip_top10
ip_top=`cat $logfile/log_ip_top10 | head -1 | awk '{print $1}'`
# 單位時間[1分鐘]內單ip訪問次數超過200次,則觸發(fā)郵件報警
if [[ $ip_top -gt 200 ]];then
/usr/bin/python /opt/tools/send_mail.py &
fi
chmod +x /opt/nginx/sbin/nginx_log_monitor.sh
定時任務
如上腳本監(jiān)控一分鐘內的日志,因此每分鐘執(zhí)行一次:
# crontab -e */1 * * * * /bin/bash /opt/nginx/sbin/nginx_log_monitor.sh
郵件告警
這里通過python實現發(fā)送郵件
# vim /opt/tools/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.exmail.qq.com'
smtp_port = 465
from_addr = 'chenqingkang@qiniu.com'
password = os.environ.get('MAIL_PASSWD')
to_addr = ['810959120@qq.com']
# 郵件對象
msg = MIMEMultipart()
msg['From'] = _format_addr('發(fā)件人 <%s>' % from_addr)
msg['To'] = _format_addr('收件人 <%s>' % to_addr)
msg['Subject'] = Header('Warning:單ip請求次數異常', 'utf-8').encode()
# 獲取系統中要發(fā)送的文本內容
with open('/opt/nginx/logs/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()
示例
寫個腳本不停curl請求資源觸發(fā)報警:
# vim curl.sh
#!/bin/bash
#example:curl.sh http://www.qingkang.me 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
# bash curl.sh http://qingkang.me/ 5 http://qingkang.me/ 200 http://qingkang.me/ 200 http://qingkang.me/ 200 http://qingkang.me/ 200 http://qingkang.me/ 200
調低閥值觸發(fā)告警:
一分鐘內單ip請求次數超過閥值 ip:115.231.182.82 請求次數/min:27
完善
這里僅實現了郵件告警功能,實際上還可以實現自動屏蔽惡意訪問的ip??梢酝ㄟ^Nginx deny來實現,也可以iptables -I INPUT -s x.x.x.x -j DROP通過iptables屏蔽。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家能有一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

