Nginx防止DDOS攻击配置

限制每秒请求数
ngx_http_limit_req_module模块通过漏桶原理来限制单位时间内的请求数,一旦单位时间内请求数超过限制,就会返回503错误。配置需要在两个地方设置:

  • nginx.conf的http段内定义触发条件,可以有多个条件
  • 在location内定义达到触发条件时nginx所要执行的动作
例如:

http {   

 limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s; //触发条件,所有访问ip 限制每秒10个请求    ...    server {        ...      

  location  ~ \.php$ {           

 limit_req zone=one burst=5 nodelay;   //执行的动作,通过zone名字对应          

     }         

  }    

 }

参数说明:
$binary_remote_addr二进制远程地址。zone=one:10m定义zone名字叫one,并为这个zone分配10M内存,用来存储会话(二进制远程地址),1m内存可以保存16000会话。rate=10r/s;制频率为每秒10个请求。burst=5允许超过频率限制的请求数不多于5个,假设1、2、3、4秒请求为每秒9个,那么第5秒内请求15个是允许的,反之,如果第一秒内请求15个,会将5个请求放到第二秒,第二秒内超过10的请求直接503,类似多秒内平均速率限制。nodelay超过的请求不被延迟处理,设置后15个请求在1秒内处理。
限制IP连接数
ngx_http_limit_conn_module的配置方法和参数与http_limit_req模块很像,参数少,要简单很多http {    limit_conn_zone $binary_remote_addr zone=addr:10m; //触发条件    ...    server {        ...        location /download/ {            limit_conn addr 1;    // 限制同一时间内1个连接,超出的连接返回503                }           }     }
白名单设置
http_limit_conn和http_limit_req模块限制了单ip单位时间内的并发和请求数,但是如果Nginx前面有lvs或者haproxy之类的负载均衡或者反向代理,nginx获取的都是来自负载均衡的连接或请求,这时不应该限制负载均衡的连接和请求,就需要geo和map模块设置白名单:geo $whiteiplist  {        default 1;        10.11.15.161 0;    }map $whiteiplist  $limit {        1 $binary_remote_addr;        0 "";    }limit_req_zone $limit zone=one:10m rate=10r/s;limit_conn_zone $limit zone=addr:10m;
geo模块定义了一个默认值是1的变量whiteiplist,当在ip在白名单中,变量whiteiplist的值为0,反之为1
如果在白名单中--> whiteiplist=0 --> $limit="" -->  不会存储到10m的会话状态(one或者addr)中 --> 不受限制
反之,不在白名单中 --> whiteiplist=1 --> $limit=二进制远程地址 -->存储进10m的会话状态中 --> 受到限制
修改最大连接数
最大连接数不够的话,nginx日志中会出现"Too many open files"错误。系统默认的1024太小了,在/etc/security/limits.conf中增加:
* soft nproc 65535* hard nproc 65535* soft nofile 65535* hard nofile 65535
iptables限制tcp连接和频率
通过上述的配置,cc攻击流量就处在302中了,但是保险起见对ip进行连接频率和并发限制,限制单ip连接和频率,在/etc/sysconfig/iptables中加入:
#单个IP在60秒内只允许新建20个连接-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m recent --update --seconds 60 --hitcount 20 --name DEFAULT --rsource -j DROP-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m recent --set --name DEFAULT --rsource#控制单个IP的最大并发连接数为20-I INPUT -p tcp --dport 80 -m connlimit  --connlimit-above 20 -j REJECT  #每个IP最多20个初始连接-A INPUT -p tcp --syn -m connlimit --connlimit-above 20 -j DROP

这样配置后,单个ip能建立的连接不是只有20个,具体能建立多少连接还要看tcp的超时设置,但单个ip不会建立大量的tcp连接消耗系统资源。
使用fail2ban屏蔽攻击ip
通过上面设置nginx后,cc攻击请求变为302,直接由性能强劲的nginx处理。但是攻击ip还是在不停的访问服务器,消耗着服务器的资源,一旦达到一定数量级,也会严重影响到系统的性能,所以通过分析nginx的访问日志彻底屏蔽这些ip。

安装fail2ban并升级iptables至最新:
yum install -y epel-release yum install -y fail2ban iptables python-inotify
先看下我nginx的访问日志格式 :
log_format  main  '$remote_addr $status $request $body_bytes_sent [$time_local]  $http_user_agent $http_referer  $http_x_forwarded_for $upstream_addr $upstream_status $upstream_cache_status $upstream_response_time';
攻击日志的效果:
159.138.198.106 302 GET /auth?url=/ HTTP/1.1 235 [17/Oct/2015:21:06:22 +0800]  Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.4.10 (KHTML, like Gecko) Version/8.0.4 Safari/600.4.10 -  - - - - -
cc攻击的ip会经过nginx和lua处理后,访问状态变为302,根据nginx的访问日志格式,过滤这些ip和302状态,加入黑名单即可。
新建fail2ban的规则文件/etc/fail2ban/filter.d/nginx-302-cc.conf,内容为:
[Definition]failregex = 302.(GET|POST)*.*HTTP/1.*$ignoreregex =
新建fail2ban的配置文件/etc/fail2ban/jail.d/nginx-anti-302.conf,内容为:
[nginx-anti-302]enabled = trueport = httpfilter = nginx-302-cclogpath = /opt/nginx/logs/52os.net/access_web.logfindtime = 60     #检测60秒内的日志bantime = 900     #屏蔽ip的时间为15分钟maxretry = 90      #达到90次就屏蔽    backend = pyinotify #使用pyinotify检测日志变化,被攻击时检测海量日志时性能最好    banaction = iptables-ipset-proto6-allports  #使用ipset屏蔽IP,使用iptables屏蔽大量IP需要时非常慢,并且资源占用非常大
访客访问一次网站会产生2次302,这样配置后60秒内允许45次正常的访问,基本上不会屏蔽正常访客。

如果使用iptables屏蔽,需注意fail2ban-0.9.3在执行iptables命令时,会加上了-w参数防止规则冲突,iptables-1.4.20以后才有这个参数,而CentOS 6 的iptables是1.4.7,导致iptables规则添加失败,解决方法是删除iptables-common.conf中的
sed -i 's/iptables = iptables /iptables = iptables/' /etc/fail2ban/action.d/iptables-common.conf
启动fail2ban :
service fail2ban start   

通过以上设置实现了:
  • 增大了系统的吞吐量
  • cc流量直接由高性能的nginx返回302,不会proxy_pass到后端的服务器或应用
  • 限制单个ip建立的tcp连接数量和频率
  • 恶意攻击ip实时黑名单

你可能感兴趣的:(Nginx防止DDOS攻击配置)