Nginx对同一IP限速限流

  Nginx通过limit_conn_zone和limit_req_zone对同一个IP地址进行限速限流,可防止DDOS/CC和flood攻击,这类文章网上比较多,但是limit_req_zone中burst漏桶原理说得清楚的却很少。

limit_conn_zone是限制同一个IP的连接数,而一旦连接建立以后,客户端会通过这连接发送多次请求,那么limit_req_zone就是对请求的频率和速度进行限制。

首先看看限制连接数,在Nginx的http配置如下:

limit_conn_zone $binary_remote_address zone=addr:10m;

然后在Nginx的server段配置如下:

limit_conn addr 2;

这里两行虽然不是在一起配置,它们之间通过addr这个变量名联系在一起。你可以对某个目录或指定后缀比如.html或.jpg进行并发连接限制,因为不同资源连接数是不同的,对于主要的.html文件并发数是两个就够了,但是一个html页面上有多个jpg/gif资源,那么并发两个肯定是不够,需要加大连接数,但是也不能太大。

有了连接数限制,相当于限制了客户端浏览器和Nginx之间 的管道个数,那么浏览器通过这个管道运输请求,如同向自来水管中放水,水的流速和压力对于管道另外一端是有影响的。为了防止不信任的客户端通过这个管道疯狂发送请求,对我们的耗CPU的资源URL不断发出狂轰滥炸,必须对请求的速度进行限制,如同对水流速度限制一样。

在Nginx.conf的http段配置:

limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;

在Nginx.conf的server段配置

limit_req zone=one burst=10;

这里引入burst漏桶原理,结合rate速率每秒5个请求(rate=5r/s)解释如下:

  • rate=5r/s:从单一IP地址每秒5个请求是允许的,
  • burst=10:允许超过频率rate限制的请求数不多于10个
  • 当每秒请求超过5个,但是在10个以下,也就是每秒请求的数量在5到10之间的请求将被延时delay,虽然这里没有明写delay,默认是延时,因为漏洞其实类似队列Queue或消息系统,当每秒请求数量超过最低速率每秒5个时,多余的请求将会进入这个队列排队等待。如同机场安检,一次放入5个,多于5个,小于10个的排队等待,注意:这个队列或漏洞是以每秒为单位的
  • 如果每秒请求数超过10个,也就是burst的限制,那么也不排队了直接回绝,返回503 http。也就是说排队长度不能超过10个。

上述使用默认延时也就是队列的方式对于一个页面如果有很多资源需要加载,那么通过排队延时加载无疑对服务器冲击小,而且防止攻击者对同一个资源发出很多请求。

如果我们使用nodelay:

limit_req zone=one burst=10 nodelay;

这表示,如果每秒请求在5-10个之间会尽快完成,也就是以每秒10个速率完成,超过每秒10+5也就是15个就立即返回503,因此nodelay实际没有了延时,也就取消了队列等候过渡。

在Twitter Facebook LinkedIn这类大型网站中,由于访问量巨大,通常会在http服务器后面放置一个消息队列,比如Apache Kafka,用来排队大量请求,因此,对于中小型网站,推荐使用delay方案,而不要写明nodelay,但是网络上其他各种文章几乎都是推荐nodelay.

最后,一个带宽限制,如下:

limit_rate 50k;
limit_rate_after 500k;

当下载的大小超过500k以后,以每秒50K速率限制。

上面总结了三个限速限流设置方式,还有一种能够防止POST攻击,黑客通过发出大量POST请求对网站各种URL进行试探攻击,可以通过下面方式防止:

http {
... #nginx.conf 配置
#如果请求类型是POST 将ip地址映射到 $limit 值
map $request_method $limit {
default "";
POST $binary_remote_addr;
}
#创造10mb zone内存存储二进制ip
limit_req_zone $limit zone=my_zone:10m rate=1r/s;
}  

 

 

Nginx提高安全与性能的最好配置

性能专题