IP的黑白名单
有时候往往有些需求,可能某些接口只能开放给对应的合作商,或者购买/接入API
的合作伙伴,那么此时就需要实现类似于IP
白名单的功能。而有时候有些恶意攻击者或爬虫程序,被识别后需要禁止其再次访问网站,因此也需要实现IP
黑名单。那么这些功能无需交由后端实现,可直接在Nginx
中处理。
Nginx
做黑白名单机制,主要是通过allow、deny
配置项来实现:
allow xxx.xxx.xxx.xxx; # 允许指定的IP访问,可以用于实现白名单。
deny xxx.xxx.xxx.xxx; # 禁止指定的IP访问,可以用于实现黑名单。
要同时屏蔽/开放多个IP
访问时,如果所有IP
全部写在nginx.conf
文件中定然是不显示的,这种方式比较冗余,那么可以新建两个文件BlocksIP.conf、WhiteIP.conf
:
# --------黑名单:BlocksIP.conf---------
deny 192.177.12.222; # 屏蔽192.177.12.222访问
deny 192.177.44.201; # 屏蔽192.177.44.201访问
deny 127.0.0.0/8; # 屏蔽127.0.0.1到127.255.255.254网段中的所有IP访问
# --------白名单:WhiteIP.conf---------
allow 192.177.12.222; # 允许192.177.12.222访问
allow 192.177.44.201; # 允许192.177.44.201访问
allow 127.45.0.0/16; # 允许127.45.0.1到127.45.255.254网段中的所有IP访问
deny all; # 除开上述IP外,其他IP全部禁止访问
分别将要禁止/开放的IP
添加到对应的文件后,可以再将这两个文件在nginx.conf
中导入:
http{
# 屏蔽该文件中的所有IP
include /soft/nginx/IP/BlocksIP.conf;
server{
location xxx {
# 某一系列接口只开放给白名单中的IP
include /soft/nginx/IP/blockip.conf;
}
}
}
对于文件具体在哪儿导入,这个也并非随意的,如果要整站屏蔽/开放就在http
中导入,如果只需要一个域名下屏蔽/开放就在sever
中导入,如果只需要针对于某一系列接口屏蔽/开放IP
,那么就在location
中导入。
当然,上述只是最简单的
IP
黑/白名单实现方式,同时也可以通过ngx_http_geo_module、ngx_http_geo_module
第三方库去实现(这种方式可以按地区、国家进行屏蔽,并且提供了IP
库)。
自动封杀IP
- 里面放需要封禁的IP,格式如下
- 在ngnix的conf目录下创建一个
blockip.conf
文件
deny 1.2.3.4;
- 在ngnix的HTTP的配置中添加如下内容
include blockips.conf;
- 重启 ngnix
/usr/local/nginx/sbin/nginx -s reload
- 然后你就会看到IP被封禁了,你会喜提403;
- 小思考:如何实现使用ngnix自动封禁ip的功能
1.AWK统计access.log,记录每分钟访问超过60次的ip,然后配合nginx进行封禁
2.编写shell脚本
3.crontab定时跑脚本
好了上面操作步骤列出来了,那我们先来实现第一个吧
操作一:AWK统计access.log,记录每分钟访问超过60次的ip
awk '{print $1}' access.log | sort | uniq -cd | awk '{if($1>60)print $0}'
1. awk '{print $1}' access.log 取出access.log的第一列即为ip。
2. sort | uniq -cd 去重和排序
3. awk '{if($1>60)print $0}' 判断重复的数量是否超过60个,超过60个就展示出来
操作二:编写shell脚本,实现整体功能(写了注释代码)
#不能把别人IP一直封着吧,这里就清除掉了
echo "" > /usr/local/nginx/conf/blockip.conf
#前面最开始编写的统计数据功能
ip_list=$(awk '{print $1}' access.log | sort | uniq -cd | awk '{if($1>60)print $0}')
#判断这个变量是否为空
if test -z "$ip_list"
then
#为空写入 11.log中,并重新启动ngnix
echo "为空" >> /usr/local/nginx/logs/11.log
/usr/local/nginx/sbin/nginx -s reload
else
#如果不为空 前面加上 deny格式和ip写入blockip.conf中
echo "deny" $ip_list > /usr/local/nginx/conf/blockip.conf
#因为前面携带了行数,所有我们需要去除掉前面的行数,写入后在读取一次
ip_list2=$(awk '{print $3}' /usr/local/nginx/conf/blockip.conf)
#最后再把读取出来的值,在次写入到blockip.conf中
echo "deny" $ip_list2";"> /usr/local/nginx/conf/blockip.conf
#重启ngnix
/usr/local/nginx/sbin/nginx -s reload
#清空之前的日志,从最新的开始截取
echo "" > /usr/local/nginx/logs/access.log
fi
操作三:使用crontab定时,来实现访问每分钟超过60的
crontab -e
* * * * * cd /usr/local/nginx/logs/ && sh ip_test.sh 每一分钟运行一次
systemctl restart crond.service 重启一下配置既可