Nginx动态黑名单

没挂上CDN

没使用CDN的情况下,通过 remote_addr 可获取用户的真实IP,进而利用 nginx 的 deny 功能来禁止指定IP访问。

nginx的accesslog日志格式:

1
2
3
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$request_time"';

conf 目录新建 blacklist.conf

添加 blacklist.conf 到配置文件中

  • 全站屏蔽:把 include blacklist.conf; 放到 http{ ... } 语句块中。
  • 单独站点屏蔽:把 include blacklist.conf; 放到网站对应的 server{ ... } 语句块中。

编写脚本 auto_add_blacklist.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
conf_path=/usr/local/nginx/conf/blacklist.conf
log_path=/usr/local/nginx/logs/access.log
nginx_command=/usr/local/nginx/sbin/nginx
spider="Google|Baidu|msnbot|FeedSky|Sogou|360|bing|yahoo"
# 实时查询日志最后的5万条记录,过滤掉正常的蜘蛛访问,对用户真实ip访问量做统计,这段时间内访问量超过峰值会自动添加ip到黑名单文件
tail -n50000 ${log_path} | \
awk '{print $1,$12,$14}'|grep -i -v -E ${spider}| \
awk '{print $1}'|sort|uniq -c|sort -rn| \
awk '{ if($1 > 1000) print "deny "$2 ";"}' > ${conf_path}
${nginx_command} -t
if [ $? -eq 0 ]
then
${nginx_command} -s reload
fi

添加任务计划:

1
2
# 半小时检查一次,自动添加ip黑名单
*/30 * * * * sh /root/crontab_sh/auto_add_blacklist.sh

重启 crond 服务。

该方法可以防范少量的DDOS攻击,也可用于高并发时临时限制访问量偏高的ip。

挂上CDN