当 location 指令包含变量时,它无效

当 location 指令包含变量时,它无效

我想要的是

对于我的/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 处理程序配置。将该位置设为内部位置可以确保它不会被直接访问(只能通过重写规则)。

相关内容