关于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