我想要的是
对于我的/admin
位置,将几个受信任的 IP 地址列入白名单,并阻止所有其他 IP 地址。
我拥有的
http {
map $remote_addr $admin_block_path {
default "/admin";
1.1.1.1 "/not-admin";
8.8.8.8 "/not-admin";
}
# …
server {
add_header X-Test-Admin "$admin_block_path";
location $admin_block_path {
return 403;
}
}
}
这个想法是使用map
有条件地确定要阻止来自访问者 IP 地址的路径。将其存储在变量中,并在 中使用该变量location
。如果请求来自不受信任的 IP,则变量将包含/admin
,因此该位置将阻止/admin
。
问题是什么
不会location
阻止访问/admin
。
- 我可以确认使用
add_header
变量是否根据 IP 地址正确设置。当从不受信任的 IP 访问时,我确实会得到/admin
,而/non-admin
当从受信任的 IP 访问时,则会得到 。 - 如果我
location $admin_block_path
用硬编码替换location /admin
,请求就会被阻止 - 尝试使用双引号,没有效果
- 尝试将斜线放在变量之外,没有效果
笔记
不幸的是,我不能简单地将allow
/硬编码deny
到某个/admin
位置,因为这会覆盖我在配置中其他地方的 PHP 传递配置。因此,/admin
只有当我知道无论如何我都会拒绝请求并且不需要 PHP 时,我才需要有一个专用的位置。
Nginx 版本:1.20.1
答案1
nginx 配置中的所有位置都在启动时编译。您不能将变量用作location
指令参数(也不能在正则表达式模式中或与其他指令一起使用变量)。此外,当 nginx 指令文档没有明确说明您可以将变量用作某些指令的参数时,通常意味着您不能这样做。您应该使用其他技术来实现您想要的效果。解决方案之一可以是以下方法:
map $remote_addr $admin_block_path {
1.1.1.1 "";
8.8.8.8 "";
default 1;
}
server {
if ($admin_block_path) {
rewrite ^/admin /blocked;
}
location = /blocked {
internal;
return 403;
}
...
}
精确匹配的位置比正则表达式的位置具有更高的优先级,因此它不会破坏您的 PHP 处理程序配置。将该位置设为内部位置可以确保它不会被直接访问(只能通过重写规则)。