1

I have a directory (www/nginx/website1/private) that I do not want to be accessible by web browser, but which must be accessible by the php applications relying on that directory's content.

I have tried everything I can think of, and read similar questions on here; nothing I have tried has worked.

I have tried:

location /private/ {
allow 127.0.0.1;
deny all;
return 404; # do not want to acknowledge existence of files. return 404
}

It doesn't work. If I navigate directly to the php file, it will process the php file -- which I have confirmed by adding an echo command to the php file.

This is my current nginx.conf file (without any of my failed attempts). What do I need to add (and where) to block access in the way I described above?

Thank you very much!

user www;
worker_processes  4;
error_log /var/log/nginx/error.log info;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
     # Set size for max uploaded content
        client_max_body_size 0; #max size disabled
        client_header_timeout 30m;
        client_body_timeout 30m;
        access_log /var/log/nginx/access.log;
        ## Block spammers ##
        include blockips.conf;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name REDACTED;
        root /usr/local/www/nginx;
        index index.php index.html index.htm;

         listen              443 ssl;
         server_name    REDACTED
    ssl_certificate     REDACTED;
    ssl_certificate_key  REDACTED;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;

### case insensitive http user agent blocking  ###
if ($http_user_agent ~*
(Googlebot|AdsBot-Google|Googlebot-images|msnbot|Bingbot|AltaVista|archive|archive.is|Slurp)
) {
    return 403;
}

## Only allow these request methods ##
     if ($request_method !~ ^(GET|HEAD|POST)$ ) {
         return 444;
     }
## Do not accept DELETE, SEARCH and other methods ##

        location / {
            try_files $uri $uri/ =404;
        }

        error_page      500 502 503 504  /50x.html;
        location = /50x.html {
            root /usr/local/www/nginx-dist;
        }

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $request_filename;
                include fastcgi_params;
        }
    }
}
hegemon
  • 13
  • 5

1 Answers1

0

As location directive documentation tells, regular expressions are matched after prefix matches have been tried, and regular expression matches win in that case.

To prevent this behavior, one must use the ^~ modifier in location block.

So, your blocking rule should look like this:

location ^~ /private/ {
    allow 127.0.0.1;
    deny all;
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        include fastcgi_params;
    }
}

We also need to duplicate the PHP processing block here, because the ^~ modifier prevents the main PHP block from being used.

One cannot use return here, deny will always return 403 error code.

If you want another error code, I guess your only option is to implement the access control in your PHP scripts.

EDIT: Updated according to Alexey's comment.

Tero Kilkanen
  • 34,499
  • 3
  • 38
  • 58