Nginx http_limit_req模块详解
简介
在配置nginx的过程中我们需要考虑受到攻击或恶意请求的情况,比如单用户恶意发起大量请求,这时http_limit_req模块可以帮助我们对其进行限制。
ngx_http_limit_req_module模块用于限制请求的处理速率,特别是单一的IP地址的请求的处理速率。使用漏桶算法进行限制。
官方英文文档: http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
配置示例
http { limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s; limit_req_zone $binary_remote_addr$uri zone=two:10m rate=1r/s; ... server { ... location /search/ { limit_req zone=one burst=10 nodelay; limit_req zone=two burst=5 nodelay; } ... }
此配置代表:
- 对于同一ip不同请求地址,限制平均速率为5请求/秒,超过部分进行延迟处理,若超过10请求/秒,丢弃超过部分。
- 对于同一ip相同请求地址,限制平均速率为1请求/秒,超过部分进行延迟处理,若超过5请求/秒,丢弃超过部分。
基本指令
limit_req_zone
语法:
limit_req_zone key zone=name:size rate=rate;
配置段:http
此指令用于声明请求限制zone,zone可以保存各种key的状态,name是zone的唯一标识,size代表zone的内存大小,rate指定速率限制。
参数详解:
1.key
若客户的请求匹配了key,则进入zone。可以是文本、变量,通常为Nginx变量。
如$binary_remote_addr(客户的ip),$uri(不带参数的请求地址),$request_uri(带参数的请求地址),$server_name(服务器名称)。
支持拼接组合使用,如$binary_remote_addr$uri。
2.zone
使用zone=test,指定此zone的名字为test。
3.size
在zone=name后面紧跟:size,指定此zone的内存大小。如zone=name:10m,代表name的共享内存大小为10m。通常情况下,1m可以保存16000个状态。
4.rate
使用rate=1r/s,限制平均1秒不超过1个请求。使用rate=1r/m,限制平均1分钟不超过1个请求。
例子:
limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s; limit_req_zone $binary_remote_addr$uri zone=two:10m rate=1r/s;
同一ip不同请求地址,进入名为one的zone,限制速率为5请求/秒。
同一ip同一请求地址,进入名为two的zone,限制速率为1请求/秒。
limit_req
语法:
limit_req zone=name [burst=number] [nodelay];
配置段:http,server,location
此指令用于设置共享的内存zone和最大的突发请求大小。
若请求速率超过了limit_req_zone中指定的rate但小于limit_req中的burst,则进行延迟处理,若再超过burst,就可以通过设置nodelay对其进行丢弃处理。
参数详解:
1.zone
使用zone=name指定使用名为name的zone,这个zone之前使用limit_req_zone声明过。
2.burst(可选)
burst用于指定最大突发请求数。许多场景下,单一地限制rate并不能满足需求,设置burst,可以延迟处理超过rate限制的请求。
3.nodelay(可选)
如果设置了nodelay,在突发请求数大于burst时,会丢弃掉这部分请求。因为如果只是延迟处理,就像”漏斗“,一旦上面加得快(请求),下面漏的慢(处理速度),”漏斗”总会有溢出的时候。这时,丢弃掉溢出的部分就显得很有意义了。
例子
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location /search/ { limit_req zone=one burst=5; } }
单客户分为三种情况
- 请求速率 < rate(1r/s),正常处理
- rate(1r/s) < 请求速率 < burst(5r/s),大于rate部分延迟
- burst(5r/s) < 请求速率,大于burst部分丢弃(返回503服务暂时不可用)
limit_req_status
语法:
limit_req_status 503;
配置段:http,server,location
设置要响应拒绝的请求而返回的状态代码(默认为503服务不可用)。
limit_req_log_level
语法
limit_req_log_level info | notice | warn | error;
配置段:http,server,location
设置当速率超过限制时记录日志的级别。
geo结合
上边的是对所有IP限速,如果想设置限速白名单可按照如下配置:
http { geo $whiteiplist { default 0; 127.0.0.1 1; 172.16.0.0 1; } map $whiteiplist $limit { 0 $binary_remote_addr 1 ""; } limit_req_zone $limit zone=why_req:10m rate=5r/s; }
说明:
- geo指令定义一个白名单$whiteiplist, 默认值为1, 所有都受限制。 如果客户端IP与白名单列出的IP相匹配,则$whiteiplist值为0也就是不受限制。
- map指令是将$whiteiplist值为1的,也就是受限制的IP,映射为客户端IP。将$whiteiplist值为0的,也就是白名单IP,映射为空的字符串。
- limit_conn_zone和limit_req_zone指令对于键为空值的将会被忽略,从而实现对于列出来的IP不做限制。