Ограничение доступа к одному контроллеру приложения MVC с помощью Nginx
У меня есть приложение MVC, где один контроллер должен быть доступен только с нескольких ips (этот контроллер является ловушкой обратного вызова для oauth-токена - для google / fb api-токенов). Мой конф выглядит так:
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 игнорируются. Я не понимаю почему...
1 ответ
Причина, по которой он всегда перезаписывается, заключается в том, что директива rewrite оценивается во время фазы перезаписи, которая находится перед фазой доступа, где оцениваются разрешения и запреты. Их порядок появления в файле не имеет значения. Вы можете решить эту проблему двумя способами: либо не использовать перезапись в 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;
    }
    ...
}