CC攻击,DDoS的一种,针对URL进行攻击,持续时间长,危害大。
Nginx防CC限制
在nginx.conf
中http模块
添加如下代码(定义触发条件):
1 2 3
| limit_req_zone $binary_remote_addr zone=one:10m rate=30r/s; limit_conn_zone $binary_remote_addr zone=addr:10m;
|
若使用CDN将$binary_remote_addr
更改为$http_x_forwarded_for
在网站的server模块
添加如下代码(定义达到触发条件时nginx所要执行的动作):
1 2
| limit_req zone=one burst=20 nodelay; limit_conn addr 15;
|
ngx_http_limit_req_module模块是通过漏桶原理来限制单位时间内的请求数,一旦单位时间内请求数超过限制,就会返回503错误。
ngx_http_limit_conn_module模块则是限制IP连接数
效果:某ip访问过于频繁,打印的日志里会出现503错误
分割Nginx日志
为后续分析方便,把正常日志、错误日志、拦截日志分开
在nginx.conf
中http模块
添加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| log_format main '[$time_local] "$request" $status $body_bytes_sent "$remote_addr"';
map $status $normal { ~^2 1; ~^3 1; default 0; } map $status $notfound { ~^4 1; default 0; } map $status $abnormal { ~^5 1; default 0; }
|
定义日志格式以及三个变量,$normal、$notfound、$abnormal,分别表示正常日志、拦截日志(40X)、系统异常日志。
在网站的server模块
添加如下代码:
1 2 3
| access_log /data/wwwlogs/www.log combined if=$normal; access_log /data/wwwlogs/www-error.log main if=$abnormal; access_log /data/wwwlogs/www-not-found.log combined if=$notfound;
|
定义日志输出到三个文件
禁止IP
添加完防CC限制和日志分割后,可以再error.log中看到出现许多503错误,接下来就需要将那些日志中的IP ban掉
添加真实IP变量
在nginx.conf
中http模块
添加如下代码:
1 2 3 4
| map $http_x_forwarded_for $clientRealIp { "" $remote_addr; ~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr; }
|
新增禁止IP脚本
将下列代码放在/usr/local/bin/nginx_deny_ctl.sh
中,并赋予可执行权限
NGINX_BIN和DENY_CONF需要根据实际情况填写
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #!/bin/bash
NGINX_BIN=/usr/local/nginx/bin/nginx DENY_CONF=/usr/local/nginx/conf/deny_conf
COLOR_RED=$( echo -e "\e[31;49m" ) COLOR_GREEN=$( echo -e "\e[32;49m" ) COLOR_RESET=$( echo -e "\e[0m" )
rep_info() { echo;echo -e "${COLOR_GREEN}$*${COLOR_RESET}";echo; } rep_error(){ echo;echo -e "${COLOR_RED}$*${COLOR_RESET}";echo;exit 1; }
reload_nginx() { $NGINX_BIN -t >/dev/null 2>&1 && \ $NGINX_BIN -s reload && \ return 0 }
pre_check() { test -f $NGINX_BIN || rep_error "$NGINX_BIN not found,Plz check and edit." test -f $DENY_CONF || rep_error "$DENY_CONF not found,Plz check and edit." MATCH_COUNT=$(show_list | grep -w $1 | wc -l) return $MATCH_COUNT }
create_rule() { test -f $DENY_CONF/$1.conf && \ rep_error "$DENY_CONF/$1.conf already exist!." cat >$DENY_CONF/$1.conf<<EOF if (\$clientRealIp ~* "$1") { return 444; break; } EOF test -f $DENY_CONF/$1.conf && \ rep_info "$DENY_CONF/$1.conf create success!" && \ reload_nginx exit 0
rep_error "$DENY_CONF/$1.conf create failed!" && \ exit 1 }
del_rule() { rm -f $DENY_CONF/$1.conf reload_nginx exit 0 }
case $1 in "-a"|"--add" ) create_rule $2; ;; "-d"|"--del" ) del_rule $2 ;; esac
|
测试是否正常添加删除IP:
1 2
| /usr/local/bin/nginx_deny_ctl.sh -a 1.2.3.4 /usr/local/bin/nginx_deny_ctl.sh -d 1.2.3.4
|
增添deny目录
在网站的server模块
添加如下代码:
根据实际情况填写
配置fail2ban
进行自动过滤禁止
过滤器filter:/etc/fail2ban/filter.d/nginx-bad-ip.conf
1 2 3 4 5
| [Definition]
failregex = ^.* "(GET|POST|HEAD).*HTTP.*" (502|503) \d+ "(-|<HOST>)"$
ignoreregex =
|
操作action:/etc/fail2ban/action.d/nginx-deny.conf
1 2 3 4 5 6 7
| [Definition] actionstart = actionstop = actioncheck = actionban = /usr/local/bin/nginx_deny_ctl.sh -a <ip> actionunban = /usr/local/bin/nginx_deny_ctl.sh -d <ip> [Init]
|
配置jail:/etc/fail2ban/jail.d/nginx.local
1 2 3 4 5 6 7 8
| [nginx-deny] enabled = true filter = nginx-bad-ip action = nginx-deny logpath = /data/wwwlogs/www-error.log maxretry = 1 findtime = 100 bantime = 86400
|
logpath需要配置为网站错误日志路径
重启服务
重新启动Nginx和fail2ban服务,打一发CC,静候效果。
我的阈值随便配的,请自行琢磨适合自己的阈值。