nginx 在一个“位置”中基于 URI 阻止 IP

Bre*_*bad 7 nginx ip block

当前有一个位置块 /

  location / {
    root  /var/www/docs;
    proxy_pass  http://backend;
    proxy_buffering     on;
    proxy_buffer_size   64k;
    proxy_buffers       256   64k;
  }
Run Code Online (Sandbox Code Playgroud)

需要通过IP过滤。

理想情况下,为了减少 中相同指令的重复次数location,我想在location块内执行测试

  location / {

    if ($uri ~ '^/(abc|def|ghi)') {
        allow 10.0.0.0/8;
        allow 1.2.3.4;
        deny all;
    }

    root  /var/www/docs;
    proxy_pass  http://backend;
    proxy_buffering     on;
    proxy_buffer_size   64k;
    proxy_buffers       256   64k;
  }
Run Code Online (Sandbox Code Playgroud)

不幸的是,似乎allow/deny指令不能在if块中使用。

/etc/nginx/sites-enabled/mysite:20 中不允许使用“允许”指令

有没有一种优雅的方法来执行测试而不重复location块?

(喜欢

  location ~ /(abc|def|ghi) {

        allow 10.0.0.0/8;
        allow 1.2.3.4;
        deny all;

        ... 5 other lines root,proxy...
   }

  location  / {

        ... 5 other lines root,proxy...
   }
Run Code Online (Sandbox Code Playgroud)

)

Koe*_*en. 8

就像 coredump 所说的,不,使用多个位置。

但是可以使location块的内容不那么重复。这里的关键是一个location包含rootproxy_...指令的命名块。

例如:

location / {
  try_files $uri @proxy;
}
location ~ /(abc|def|ghi) {
  allow 10.0.0.0/8;
  allow 1.2.3.4;
  deny all;

  try_files $uri @proxy;
}
location @proxy {
  root  /var/www/docs;
  proxy_pass  http://backend;
  proxy_buffering     on;
  proxy_buffer_size   64k;
  proxy_buffers       256   64k;
}
Run Code Online (Sandbox Code Playgroud)

可能更好的是将root指令放在所有location块之外。


man*_*nyk 5

首先,您必须定义一个变量来保存您的 IP 过滤器。这进入了 nginx 配置的http部分:

map $remote_addr (or $http_x_forwarded_for if behind a proxy) $allowed {
        default deny;
        ~\s*111.222.333.444$ allow;
        ~\s*333.444.555.*$   allow;
    }
Run Code Online (Sandbox Code Playgroud)

然后在服务器部分编写 if 构造并通过变量$allowed的内容过滤访问位置:

location / {
        if ( $allowed = "deny" ) { return 403; }
        #...
    }
Run Code Online (Sandbox Code Playgroud)