简介

在日常业务场景中可能存在恶意用户频繁访问系统,占用系统资源,影响正常用户访问,我们有许多方案杜绝此类问题发生,例如增加验证码,应用内限制访问次数,网关 ip 封禁等等。本次介绍如何利用 Nginx 和 shell 脚本自动化封禁访问 ip。

Nginx 封禁 ip 或 ip 段

封禁 ip/ip 段语法

powershell
1
2
deny 1.2.3.4;
deny 91.212.45.0/24;

允许 ip/ip 段语法

powershell
1
2
allow 1.2.3.4;
allow 91.212.45.0/24;

新建 /usr/local/nginx/conf/vhosts/blockip.conf,将封禁 ip/ip 段的语句放入到 blockip.conf

根据放入的语句块实现封禁 ip 的范围:

  • include vhosts/blockip.conf 放在 server 语句块,则单独封禁某个网站
  • include vhosts/blockip.conf 放在 http 语句块,则封禁所有网站

记得在 nginx.conf 导入 blockip.conf

禁用ip配置

shell 脚本自动化封禁 ip

awk

AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。后面会详细介绍。

自动化封禁 ip 的思路:

1、统计访问日志的 ip 并去重排序

2、计算超过特定访问速率(每分钟 60 次)的 ip

3、将 ip 记录在 vhosts/blockip.conf 并灰度发布

4、crontab 定时运行脚本

shell
1
awk '{print $1}' /usr/local/nginx/logs/access.log

统计access.log

shell
1
awk '{print $1}' /usr/local/nginx/logs/access.log | sort | uniq -cd

去重和排序

shell
1
awk '{print $1}' /usr/local/nginx/logs/access.log | sort | uniq -cd | awk '{if($1>)print $0}'

计算超过特定访问速率(每分钟60次)的ip

编写 shell 脚本

shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#不能把别人IP一直封着吧,这里就清除掉了
echo "" > /usr/local/nginx/conf/vhosts/blockip.conf

#前面最开始编写的统计数据功能
ip_list=$(awk '{print $1}' /usr/local/nginx/logs/access.log | sort | uniq -cd | awk '{if($1>60)print $0}')

#获取当前时间
starttime=$(date +%Y-%m-%d\ %H:%M:%S)

#判断这个变量是否为空
if test -z "$ip_list"
then
#为空写入 blockip.log中,并重新启动ngnix
echo "$starttime 暂无封禁ip" >> /usr/local/nginx/logs/blockip.log

/usr/bin/nginx -s reload
else
#如果不为空 前面加上 deny格式和ip写入blockip.conf中
echo "deny" $ip_list > /usr/local/nginx/conf/vhosts/blockip.conf

#因为前面携带了行数,所有我们需要去除掉前面的行数,写入后在读取一次
ip_list2=$(awk '{print $3}' /usr/local/nginx/conf/vhosts/blockip.conf)

#最后再把读取出来的值,在次写入到blockip.conf中
echo "deny" $ip_list2";"> /usr/local/nginx/conf/vhosts/blockip.conf

#重启ngnix
/usr/bin/nginx -s reload
#清空之前的日志,从最新的开始截取
echo "" > /usr/local/nginx/logs/access.log

# 记录封禁ip
echo "$starttime 封禁ip $ip_list2" >> /usr/local/nginx/logs/blockip.log
fi

crontab 定时运行脚本

编辑 /etc/crontab

shell
1
* * * * * root /usr/bin/sh /usr/local/nginx/shell/blockip.sh

* * * * * 表示每分钟运行一次

root 表示运行用户

/usr/bin/sh 表示运行程序

/usr/local/nginx/shell/blockip.sh 表示运行脚本

crontab定时运行脚本

效果

为了更快达到效果,博主将访问次数改为 20 次

封禁ip效果

如果想调整每分钟的访问次数,请修改 shell 脚本

如果想调整定时任务的间隔时间,请参考 cron 表达式,修改 /etc/crontab