У меня есть приложение MVC, в котором один контроллер должен быть доступен только из нескольких IP-адресов (этот контроллер является ловушкой обратного вызова токена oauth - для токенов API google / fb). Моя конфиг выглядит так:
geo $oauth {
default 0;
87.240.156.0/24 1;
87.240.131.0/24 1;
}
server {
listen 80;
server_name some.server.name.tld default_server;
root /home/user/path;
index index.php;
location /oauth {
deny all;
if ($oauth) {
rewrite ^(.*)$ /index.php last;
}
}
location / {
if ($request_filename !~ "\.(phtml|html|htm|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|xlsx)$") {
rewrite ^(.*)$ /index.php last;
break;
}
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
Работает, но выглядит некорректно.
Мне кажется логичным следующее:
location /oauth {
allow 87.240.156.0/24;
deny all;
rewrite ^(.*)$ /index.php last;
}
Но при этом перезапись происходит все время, директивы allow и deny игнорируются. Я не понимаю почему ...
Причина, по которой он всегда перезаписывает, заключается в том, что директива перезаписи оценивается во время фазы перезаписи, которая предшествует фазе доступа, где оцениваются allow и deny. Порядок их появления в файле не имеет значения. Вы можете решить эту проблему двумя способами: либо не использовать перезапись в location / oauth для отправки запроса на фронт-контроллер, либо обрабатывать исходный IP-адрес на этапе перезаписи. Вы уже делаете последнее в своей рабочей конфигурации, но это можно сделать немного яснее:
geo $oauth_denied {
default 1;
87.240.156.0/24 0;
87.240.131.0/24 0;
}
server {
...
location /oauth {
if ($oauth_denied) { return 403; }
rewrite ^ /index.php last;
}
...
}
или:
server {
...
# include at server level so they're inherited by locations
include fastcgi_params;
location /oauth {
allow 87.240.156.0/24;
deny all;
# try_files will change $uri so all the params work
try_files /index.php =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
...
}