![Nginx:使用标头绕过速率限制](https://linux22.com/image/707686/Nginx%EF%BC%9A%E4%BD%BF%E7%94%A8%E6%A0%87%E5%A4%B4%E7%BB%95%E8%BF%87%E9%80%9F%E7%8E%87%E9%99%90%E5%88%B6.png)
如果我需要使用秘密标头来绕过速率限制,我该如何实现?
参考:
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 "";
}
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
答案1
这些问题的通常原因是,大多数这些指令不能在语句的上下文中使用if
,因此,如何能够有条件地指定不同的限制?
答案是使用中间变量——就像在链接答案中一样,使用变量设置限制,随后,这些变量的值将根据map
或if
语句而有所不同。
http {
map $http_x_secret_header $limit {
default $binary_remote_addr;
secretvalue "";
}
limit_conn_zone $limit zone=connlimit:10m;
…
参考:
答案2
FWIIW,我也看过另一个“奇怪”的答案对于您链接的问题——它是在 2011 年写的,在 2017 年早些时候只有 3 个赞成票,而您引用的 2014 年左右的最新答案有 23 个赞成票。也许有点令人惊讶的是,较早被忽略的答案实际上也没有任何问题!
以下是我对完整 MVP 配置的看法,经过全面测试:
server {
listen 7461;
error_page 429 = @slowdown;
if ($http_x_secret_header != secret_value) {
return 429;
}
location @slowdown {
#limit_...
return 200 "$uri: slowed down\n";
}
location / {
return 200 "$uri: very fast\n";
}
}
下面的测试向您展示一切正常,包括200 OK
返回了正确的代码:
%curl -H "X-Secret-Header: secret_value" localhost:7461/important/path/
/important/path/: very fast
%curl -H "X-Secret-Header: wrong_value" localhost:7461/important/path/
/important/path/: slowed down
%curl -v localhost:7461/important/path/ | & fgrep -e HTTP/ -e /important
> GET /important/path/ HTTP/1.1
< HTTP/1.1 200 OK
/important/path/: slowed down
%
所以,是的,error_page
重定向确实也有效!
让我解释一下这个奇怪答案的原因error_page
——在 nginx 中,你可以同时执行这两项操作外部的重定向(对客户端可见),以及内部的重定向(内部完成,无需向客户端发出任何中间回复)。
这种内在与外在的差异是一种很强大概念,没有它许多凉爽的技巧这是不可能的,因为配置语言足够简单,可以限制if
语句中可用的指令数量,并且不允许嵌套if
语句。
因此,使用内部重定向,$uri
可以在内部进行更改,导致您的请求在多个独立位置之间来回跳转(将每个位置视为location
DFA(确定性有限自动机)中的一个状态),直到达到所需的结果(有关这种情况的极端示例,请查看http://mdoc.su/,如图所示nginx.conf 2016)。
总结,在上面的例子中:
我们重新将
429
error_page
用作到internal
的重定向internal
location
,然后以与internal
location
处理非内部位置完全相同的方式处理它,只是添加了一些额外的变量或指令;我们还使用
=
参数来error_page
指令指示 nginx 实际上不要将429
代码发送回客户端,而是让进一步的处理决定最终的状态代码应该是什么。