我可以使用limit_req
速率限制来限制对我的服务器的所有请求。
但是我想删除某些 IP 地址(即白名单)的速率限制,并对某些其他 IP 地址使用不同的速率限制(即我希望某些 IP 的速率低至 1r/s)。
我尝试使用条件(例如if ( $remote_addr = "1.2.3.4" ) {}
),但它似乎只适用于重写规则,而不适用于速率限制规则。
答案1
最好避免使用“if”指令。当 limit_req_zone(和 limit_conn_zone)中的键为空时,不会应用限制。您可以将其与 map 和 geo 模块结合使用,以创建不应用节流限制的 IP 白名单。
此示例显示如何配置单个 IP 的并发请求数和请求率的限制。
http {
geo $whitelist {
default 0;
# CIDR in the list below are not limited
1.2.3.0/24 1;
9.10.11.12/32 1;
127.0.0.1/32 1;
}
map $whitelist $limit {
0 $binary_remote_addr;
1 "";
}
# The directives below limit concurrent connections from a
# non-whitelisted IP address to five
limit_conn_zone $limit zone=connlimit:10m;
limit_conn connlimit 5;
limit_conn_log_level warn; # logging level when threshold exceeded
limit_conn_status 503; # the error code to return
# The code below limits the number requests from a non-whitelisted IP
# to one every two seconds with up to 3 requests per IP delayed
# until the average time between responses reaches the threshold.
# Further requests over and above this limit will result
# in an immediate 503 error.
limit_req_zone $limit zone=one:10m rate=30r/m;
limit_req zone=one burst=3;
limit_req_log_level warn;
limit_req_status 503;
区域指令必须放在 http 级别,但是其他指令可以放在更底层,例如服务器或位置级别,以限制其范围或进一步调整限制。
有关更多信息,请参阅 Nginx 文档ngx_http_limit_req_module和ngx_http_limit_conn_module
答案2
您可以安全地使用命名位置,例如 if() 块中的“@location”。
看:http://wiki.nginx.org/IfIsEvil
类似这样的事情应该可以工作:
http {
limit_req_zone $binary_remote_addr zone=delay:10m rate=1r/m;
server {
...
error_page 410 = @slowdown;
if( $remote_addr != "1.2.3.4" ) {
return 410;
}
location @slowdown {
limit_req zone=delay burst 5;
...
}
location / {
...
}
}
在“location @slowdown { }”中填写与“location / { }”相同的信息,例如,如果您使用 nginx 作为反向代理,则填写 proxy_pass。