Ubertone
Ubertone

Reputation: 63

Nginx deny doesn't work for folder files

I'm trying to restrict access to my site to allow only specific IPs and I've got the following problem: when I access www.example.com deny works perfectly, but when I try to access www.example.com/index.php it returns "Access denied" page AND php file is downloaded directly in browser without processing. I do want to deny access to all the files on the website for all IPs but mine. How should I do that?

Here's the config I have:

server {
listen 80;
server_name example.com; 
root /var/www/example;

location / {
    index index.html index.php; ## Allow a static html file to be shown first
    try_files $uri $uri/ @handler; ## If missing pass the URI to front handler
    expires 30d; ## Assume all files are cachable
 allow my.public.ip;
 deny all;
}

location @handler { ## Common front handler
    rewrite / /index.php;
}
location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
    rewrite ^(.*.php)/ $1 last;
}

location ~ .php$ { ## Execute PHP scripts
    if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss

    expires        off; ## Do not cache dynamic content
    fastcgi_pass   127.0.0.1:9001;
    fastcgi_param  HTTPS $fastcgi_https;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params; ## See /etc/nginx/fastcgi_params
    }
}

Upvotes: 1

Views: 1289

Answers (2)

Ubertone
Ubertone

Reputation: 63

OK, so I've found the solution. Nginx processes the most exact regex which in this case is the regex for php files. To make the config work all further locations must be defined within / location rule except for @handler (you cannot put under any rule - only as root)

server {
listen 80;
server_name example.com; 
root /var/www/example;

    location / {
    index index.html index.php; ## Allow a static html file to be shown first
    try_files $uri $uri/ @handler; ## If missing pass the URI to front handler
    expires 30d; ## Assume all files are cachable
    allow my.public.ip;
    deny all;

    location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
        rewrite ^(.*.php)/ $1 last;
    }

    location ~ .php$ { ## Execute PHP scripts
        if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss

        expires        off; ## Do not cache dynamic content
        fastcgi_pass   127.0.0.1:9001;
        fastcgi_param  HTTPS $fastcgi_https;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params; ## See /etc/nginx/fastcgi_params
        }
}

    location @handler { ## Common front handler
        rewrite / /index.php;
    }

}

Upvotes: 0

Dayo
Dayo

Reputation: 12785

That is because your deny/allow rule applies to just one location.

Remove that and try:

server {
    listen 80;
    server_name example.com; 
    root /var/www/example;
    if ($remote_addr != "YOUR.PUBLIC.IP") {return 403;}
    ...
}

As the test is outside any specific locationblock, it will apply to all cases.

Note also that IF is not evil here since it just "returns".

Upvotes: 0

Related Questions