删掉一些二次判定(加快封禁检测,随总请求数量速度增加逐级提高/降低封禁阈值;),以及封禁IP数量统计,去重;好就好在脚本很短,也很好理解;

I. Cloudflare 下 Nginx 获取用户真实IP 地址

如果你正在使用Cloudflare,则需要对Nginx进行相关设置;

server
    {
listen 443 ssl http2;
server_name limbopro.xyz ;
...
##$server 段 添加如下段落 开始
include /home/ip.blacklist.5minutes.conf; ##黑名单位置;
set_real_ip_from 103.21.244.0/22; 
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;
real_ip_header CF-Connecting-IP;
##$server 段 添加如下段落 结束 #这些都是CF节点IP;
...
index index.html index.htm index.php default.html default.htm default.php;
...

参考 Cloudflare 下 Nginx 获取用户真实IP 地址

II. 提取Nginx.log日志

新建Shell脚本 /home/5minutes.log.sh,内容如下;(脚本存放位置与名字自己看着办)

#!/bin/bash

function define()
{
    ori_log_path="/home/wwwlogs/limbopro.xyz/access.log" #你的 Nginx 日志位置!!
    tmp_log_path="/home/5min.access.log" #提取最近5分钟Nginx日志
    date_stamp=`date -d "-5min" +%Y:%H:%M:%S` #时间提取(5分钟内)
    day_stamp=`date +%d` #日期提取
}

function gather()
{
    awk -F '[/ "\[]' -vnstamp="$date_stamp" -vdstamp="$day_stamp" '$7>=nstamp && $5==dstamp' ${ori_log_path} > ${tmp_log_path};
    log_num=`cat ${tmp_log_path} | wc -l`;
    request_time=`awk '{print $(NF-1)}' ${tmp_log_path} | awk '{sum+=$1}END{print sum}'`;
    ave_request_time=`echo | awk "{print ${request_time}/${log_num}}" `;
    /home/nginx.ban.5minutes.sh; #执行封禁脚本
    > /home/5min.access.log; #清除临时产生的5分钟日志
}

function output()
{
}

function main()
{
    define
    gather
    output
}

main

III. 我的配置参考

#!/bin/bash

function define()
{
    ori_log_path="/home/wwwlogs/limbopro.xyz/access.log"
    tmp_log_path="/home/5min_limbopro.xyz.access.log"
    date_stamp=`date -d "-5min" +%Y:%H:%M:%S`
    day_stamp=`date +%d`
}

function gather()
{
    awk -F '[/ "\[]' -vnstamp="$date_stamp" -vdstamp="$day_stamp" '$7>=nstamp && $5==dstamp' ${ori_log_path} > ${tmp_log_path};
    log_num=`cat ${tmp_log_path} | wc -l`;
    request_time=`awk '{print $(NF-1)}' ${tmp_log_path} | awk '{sum+=$1}END{print sum}'`;
    ave_request_time=`echo | awk "{print ${request_time}/${log_num}}" `;
    ipcounts=$(awk '{print $1}' /home/5min_limbopro.xyz.access.log | sort -n | uniq | wc -l);
    date=$(env LANG=en_US.UTF-8 date "+%e/%b/%Y/%R")
    echo "${date}" "网站最近5分钟总请求数为 ${log_num}" 次 >> /home/5minutes.log;
    echo "${date}" "网站最近5分钟总请求数为 ${ipcounts}" 个"(IP数量)" >> /home/5minutes.log;
    echo " " >> /home/5minutes.log;
    /home/nginx.ban.5minutes.sh;
    > /home/5min_limbopro.xyz.access.log;
}

function output()
{
    date=$(env LANG=en_US.UTF-8 date "+%e/%b/%Y/%R")
    max=200000
    if [ ${log_num} -gt $max ];
then
    cp /home/attackcheck.ddos.sh.bak /home/attackcheck.sh
/home/attackcheck.sh;
else
    cp /home/attackcheck.normal.sh.bak /home/attackcheck.sh
/home/attackcheck.sh;
fi
}

function main()
{
    define
    gather
    output
}

main

IV. 封禁脚本

新建 Shell脚本 /home/nginx.ban.5minutes.sh,内容如下;(脚本存放位置与名字自己看着办)

#!/bin/bash 
blockip=/home/ip.blacklist.5minutes.conf #黑名单位置,请把这个文件添加到 server 段下;
access=/home/5min.access.log 
for ip in $(awk '{cnt[$1]++;}END{for(i in cnt){printf("%s\t%s\n", cnt[i], i);}}' ${access} | awk '{if($1>500) print $2}') #五分钟内超过500次请求则拉黑

do
    echo "deny ${ip};" >> $blockip
    echo "deny ${ip};" >> $ipcount
    iptables -I INPUT -s ${ip} -j DROP
done
lnmp nginx reload ## nginx 重新加载配置文件

V. 定时执行

crontab -e #命令行输入
* * * * * /home/5minutes.log.sh ##设置为1分钟执行一次

手动自定义封杀脚本

有时候遇到大规模IP请求?比如1万个代理ip,直接手动封杀即可;

脚本如下:

#!/bin/bash

## 清除缓存日志
#> /home/echo_limbopro.xyz.access.log
> /home/echo_limbopro.xyz.access.before.log;
> /home/echo_limbopro.xyz.access.log;
echo -n "输入需要读取的文档(默认回车):"
read iaccess # 把键盘输入放入变量access


## 赋值到最大日志读取时间并读取日志
echo -n "输入日志最大的读取范围(分钟内):"                   # 参数-n的作用是不换行,echo默认换行
read  imaxtime # 把键盘输入放入变量maxtime

function define()
{
    ori_log_path="/home/wwwlogs/limbopro.xyz/access."${iaccess}"log" #按实际位置进行修改
    tmp_log_path="/home/echo_limbopro.xyz.access.log" #提取的临时日志位置及名字
    date_stamp=`date -d "-"${imaxtime}"min" +%Y:%H:%M:%S`
    day_stamp=`date +%d`
}

function gather()
{
    awk -F '[/ "\[]' -vnstamp="$date_stamp" -vdstamp="$day_stamp" '$7>=nstamp && $5==dstamp' ${ori_log_path} > ${tmp_log_path};
    log_num=`cat ${tmp_log_path} | wc -l`;
    request_time=`awk '{print $(NF-1)}' ${tmp_log_path} | awk '{sum+=$1}END{print sum}'`;
    ave_request_time=`echo | awk "{print ${request_time}/${log_num}}" `;
    #ipcounts=$(awk '{print $1}' /home/5min_limbopro.xyz.access.log | sort -n | uniq | wc -l);
    date=$(env LANG=en_US.UTF-8 date "+%e/%b/%Y/%R")
    echo "${date}" "网站最近"${imaxtime}"分钟总请求数为 ${log_num}" 次 # >> /home/5minutes.log;
}


function main()
{
    define
    gather
 #   output
}

main


## 赋值到最大IP封禁值;
echo -n "输入最低可封杀请求数:" 
read  max                                   

## 清除上期封禁;
> /home/ip.blacklist.auto.echo.conf #如果不想清除可注释掉

## 新一轮封禁开始;
blockip=/home/ip.blacklist.auto.echo.conf
access=/home/echo_limbopro.xyz.access.log
for ip in $(awk '{cnt[$1]++;}END{for(i in cnt){printf("%s\t%s\n", cnt[i], i);}}' ${access} | awk '{if($1>'$max') print $2}') 
do 
    echo "deny ${ip};" >> $blockip 
    echo "deny ${ip};" >> /home/wwwroot/typecho/deny/index.log 
done
sleep 1s

## 重启nginx以生效;
lnmp nginx reload

##计算IP封禁数量;
catipblocks=$(nohup wc -l /home/ip.blacklist.auto.echo.conf > /home/ip.blacklist.auto.echo.conf.log);
ipblocks=$(awk '{print $1}' /home/ip.blacklist.auto.echo.conf.log);
> /home/ip.blacklist.auto.echo.conf.log;
echo ""${imaxtime}" 分钟内,符合"${max}"次请求则封禁的 IP 数量为${ipblocks}个;"
echo ""${imaxtime}" 分钟内,符合"${max}"次请求则封禁的 IP 地址如下:"
cat /home/ip.blacklist.auto.echo.conf;
echo ""${imaxtime}" 分钟内,符合"${max}"次请求则封禁的 IP 地址如上:"
echo ""${imaxtime}" 分钟内,符合"${max}"次请求则封禁的 IP 数量为${ipblocks}个;"

## 查看IP访问数量;
ipnumbers=$(awk '{print $1}' ${access} | sort -n | uniq | wc -l)
echo ""${imaxtime}" 分钟内,用户发起请求的 IP 数量为${ipnumbers}个;"

#echo "最受欢迎的3个页面:"
echo -n "查看最受欢迎的页面(输入数字):"
read  maxpages;
nohup awk '{print $7}' /home/echo_limbopro.xyz.access.log | sort |uniq -c | sort -rn | head -n "${maxpages}" >> /home/hotpages.log;
echo ""${imaxtime}" 分钟内,最受欢迎的"${maxpages}"个页面:"
cat /home/hotpages.log
> /home/hotpages.log


## 清楚缓存日志;
#> /home/echo_limbopro.xyz.access.log
> /home/echo_limbopro.xyz.access.before.log;
> /home/echo_limbopro.xyz.access.log;
最后修改:2020 年 01 月 03 日 09 : 37 AM