Nginx错误日志分析及防护脚本

  • 关于iptables定时策略、crontab设置请自行去了解,建议使用”nohup &”方式执行crontab任务;

  • 该脚本可以扩展对iptables日志进行分析、某个IP在1天(或1小时)内出现多次被限制则进行更长时间限制或永久拒绝访问;

  • 对于nginx error日志可以做大小限制进行截断以减少脚本读取日志文件耗时。

# !/bin/bash
# 脚本用于Nginx错误日志检测,若30秒内来源IP地址超出10次错误视为攻击源并自动加入防火墙
# sh -x weblog_black.sh 进行跟踪调试

LOG1="/data/shell/$(date +%Y%m%d)_w$$.txt0"
LOG2="/data/shell/$(date +%Y%m%d)_w$$.txt1"
LOG3="/data/shell/$(date +%Y%m%d)_w$$.txt2"

find /data/shell/ -type f -name "*.*" -mmin +3 -exec rm -f {} \;
grep -v -i '/undefined' $NGLOG | grep "\[error\]" | cut -d',' -f2 | cut -d':' -f2 | sort -b | uniq -cd | sort -nr > $LOG1
sleep 30
grep -v -i '/undefined' $NGLOG | grep "\[error\]" | cut -d',' -f2 | cut -d':' -f2 | sort -b | uniq -cd | sort -nr > $LOG2

#for line in `cat "$LOG2"`
cat $LOG2 | while read line
  do
    ip=`echo $line | awk -F" " '{print $2}'`
    nume=`echo $line | awk -F" " '{print $1}'`        #结束访问次数
    nums=`grep $ip $LOG1 | awk -F" " '{print $1}'`    #开始访问次数
    num30=`expr $nume - $nums`
    #num30=$((nume - nums)) || num30=$[ nume - nums ]
    echo $ip $nume $nums $num30 >> $SHLOG
  if [ "$num30" -gt 10 ]; then
    /sbin/iptables -nvL IN_NGBLACK
    if [ "$?" -eq 1 ]; then
      /sbin/iptables -N IN_NGBLACK
      /sbin/iptables -I INPUT -j IN_NGBLACK
    else
      chain_sum=`/sbin/iptables -nvL IN_NGBLACK | tail -n +3 | wc -l`
      if [ "$chain_sum" -gt 100 ]; then
        /sbin/iptables -D IN_NGBLACK $chain_sum
        /sbin/iptables -D IN_NGBLACK `expr $chain_sum - 1`
      fi
    fi

    /sbin/iptables -nvL IN_NGBLACK | grep $(echo $ip) | grep DROP
    if [ "$?" -eq 1 ]; then
      /sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -m time --timestart `date +%H:%M` --timestop `date -d '+10 min' +%H:%M` -j DROP
      /sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -m limit --limit 10/min --limit-burst 10 -j ACCEPT
      #/sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -j DROP
      #sleep 600 && /sbin/iptables -D IN_NGBLACK -s $ip -p tcp -m multiport --dports 80,443 -j DROP && /sbin/iptables -D IN_NGBLACK -s $ip -p tcp -m multiport --dports 80,443 -m limit --limit 10/min --limit-burst 10 -j ACCEPT & #主进程会在后台等待子进程执行完成后退出
    else
      chain_num=`/sbin/iptables -nvL IN_NGBLACK --line-numbers | grep $(echo $ip) | grep DROP | cut -d' ' -f1`
      /sbin/iptables -D IN_NGBLACK $chain_num
      /sbin/iptables -D IN_NGBLACK `expr $chain_num - 1`
      /sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -m time --timestart `date +%H:%M` --timestop `date -d '+15 min' +%H:%M` -j DROP
      /sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -m limit --limit 10/min --limit-burst 10 -j ACCEPT
    fi
    /sbin/iptables-save > $IPTAB
  fi
done

sleep 30
grep -v -i '/undefined' $NGLOG | grep "\[error\]" | cut -d',' -f2 | cut -d':' -f2 | sort -b | uniq -cd | sort -nr > $LOG3

cat $LOG3 | while read line
  do
    ip=`echo $line | awk -F" " '{print $2}'`
    nume=`echo $line | awk -F" " '{print $1}'`        #结束访问次数
    nums=`grep $ip $LOG1 | awk -F" " '{print $1}'`    #开始访问次数
    num60=`expr $nume - $nums`
    echo $ip $nume $nums $num60 >> $SHLOG
  if [ "$num60" -gt 15 ]; then
    /sbin/iptables -nvL IN_NGBLACK
    if [ "$?" -eq 1 ]; then
      /sbin/iptables -N IN_NGBLACK
      /sbin/iptables -I INPUT -j IN_NGBLACK
    else
      chain_sum=`/sbin/iptables -nvL IN_NGBLACK | tail -n +3 | wc -l`
      if [ "$chain_sum" -gt 100 ]; then
        /sbin/iptables -D IN_NGBLACK $chain_sum
        /sbin/iptables -D IN_NGBLACK `expr $chain_sum - 1`
      fi
    fi

    /sbin/iptables -nvL IN_NGBLACK | grep $(echo $ip) | grep DROP
    if [ "$?" -eq 1 ]; then
      /sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -m time --timestart `date +%H:%M` --timestop `date -d '+10 min' +%H:%M` -j DROP
      /sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -m limit --limit 10/min --limit-burst 10 -j ACCEPT
      #/sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -j DROP
      #sleep 600 && /sbin/iptables -D IN_NGBLACK -s $ip -p tcp -m multiport --dports 80,443 -j DROP && /sbin/iptables -D IN_NGBLACK -s $ip -p tcp -m multiport --dports 80,443 -m limit --limit 10/min --limit-burst 10 -j ACCEPT & #主进程会在后台等待子进程执行完成后退出
    else
      chain_num=`/sbin/iptables -nvL IN_NGBLACK --line-numbers | grep $(echo $ip) | grep DROP | cut -d' ' -f1`
      /sbin/iptables -D IN_NGBLACK $chain_num
      /sbin/iptables -D IN_NGBLACK `expr $chain_num - 1`
      /sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -m time --timestart `date +%H:%M` --timestop `date -d '+15 min' +%H:%M` -j DROP
      /sbin/iptables -I IN_NGBLACK 1 -s $ip -p tcp -m multiport --dports 80,443 -m limit --limit 10/min --limit-burst 10 -j ACCEPT
    fi
    /sbin/iptables-save > $IPTAB
  fi
done
标签:Nginx 发布于:2019-11-03 00:25:06