简单实现自动过滤WEB攻击源IP


最近VPS负载经常会比较高,刚刚仔细检查了一下,发现有一些IP在非常频繁的向Blog发请求,大多数是关于评论和后台登陆页面的。
由此造成了fastcgi的进程非常繁忙,使得VPS本身就非常弱小的CPU一直处于高利用率的状态。
于是,我编写了一个简单的脚本,每隔1分钟从服务器日志中取出这些IP并通过iptables将其直接Block掉,用起来效果很不错。

根据我目前服务器的访问日志来看,如果在10000次请求中,有500次请求来自于同一个IP的话,那么其攻击特征就非常明显了。
另外,针对后台登陆页面和评论页面,我单独制定了更加严格的规则,那就是在10000次POST请求中,如果有50次尝试,就Block掉。

具体的脚本内容如下:
$ vim /home/rainbow/sbin/block_attack_ips.sh

#!/bin/bash

logfiles=(
/webserver/blog/logs/rainbow_access.log
/webserver/blog/logs/eric_access.log
)

whitelist=$(last | awk '{print $3}' | grep ^[1-9] | sort | uniq | xargs)
whitelist+=" 127.0.0.1 172.31.23.107 52.69.213.155"

function check_root(){
  if [ $EUID -ne 0 ]; then
    echo "This script must be run as root"
    exit 1
  fi
}

function block_ips(){
  blacklist=$@
  if [ ! -z "${blacklist}" ]; then
    for ip in ${blacklist}
    do
      if ! $(echo ${whitelist} | grep -wq ${ip}); then
        if ! $(/sbin/iptables-save | grep -wq ${ip}); then
          echo "Blocked ${ip}"
          /sbin/iptables -I INPUT -s ${ip}/32 -p tcp -m tcp --dport 80 -j DROP
        fi
      fi
    done
  fi
}

function check_post(){
  page=$1
  tailnum=$2
  retry=$3

  command="grep -w POST ${logfile} |tail -n ${tailnum} |grep -w ${page} |awk '{print \$1}' |sort |uniq -c |awk '(\$1 > ${retry}){print \$2}'"
  blacklist=$(eval ${command})
  block_ips ${blacklist}
}

function check_all(){
  tailnum=$1
  retry=$2

  command="tail -n ${tailnum} ${logfile} |awk '{print \$1}' |sort |uniq -c |awk '(\$1 > ${retry}){print \$2}'"
  blacklist=$(eval ${command})
  block_ips ${blacklist}
}

check_root
for logfile in ${logfiles[@]}
do
  check_post wp-login.php 10000 50
  check_post wp-comments-post.php 10000 50
  check_all 10000 500
done

$ chmod +x /home/rainbow/sbin/block_attack_ips.sh

配置crontab计划任务,每1分钟检查一次,并每月定时重启iptables服务清除旧的记录:
$ sudo crontab -e

*/1 * * * * /home/rainbow/sbin/block_attack_ips.sh
00 01 1 * * /etc/init.d/iptables restart

  1. No comments yet.
(will not be published)
*