На данный момент есть блок из одной локации /
location / {
root /var/www/docs;
proxy_pass http://backend;
proxy_buffering on;
proxy_buffer_size 64k;
proxy_buffers 256 64k;
}
который нужно фильтровать по 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;
}
К сожалению, кажется allow
/deny
директивы не могут использоваться в if
блок.
"allow" directive is not allowed here in /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...
}
)
Как сказал coredump, нет, используйте несколько мест.
Но можно сделать содержимое location
блоки менее повторяющиеся. Ключ здесь - именованный location
блок, содержащий root
и proxy_...
директивы.
Например:
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;
}
И, наверное, еще лучше было бы разместить root
директива вне всех location
блоки.
Сначала вам нужно определить переменную, которая будет содержать ваши IP-фильтры. Это входит в http раздел конфигурации nginx:
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;
}
затем в сервер вы пишете конструкцию if и фильтруете место доступа по содержимому переменной $ разрешено:
location / {
if ( $allowed = "deny" ) { return 403; }
#...
}
Обычно в таких случаях могут помочь «вложенные локации» ...
location / {
root /var/www/docs;
allow all;
location /admin {
deny 1.2.3.4;
}
}
... но не все директивы унаследованы во вложенных местах. К сожалению, но точно proxy_pass
, fastcgi_pass
и подобные не наследуются ... Таким образом, предложенное ранее решение (с @ namedlocation) является правильным в этом случае. Вы также можете использовать директиву include
для "блока proxy_pass", конечно.
Нет. Используйте несколько locations
, это может выглядеть некрасиво, но у вас будет меньше шансов если безумие.
Также помните, что nginx сначала обрабатывает совпадения регулярного выражения, и если ни одно из них не соответствует, он пробует наиболее конкретное буквальное местоположение, являющееся location /
своего рода поймать все расположение. Зная, что вы можете уменьшить количество необходимых вам мест. Взгляни на этот документ чтобы увидеть, как обрабатываются запросы.