Restricting access to files and directories on Nginx by IP

I’m trying to lock down access to WP-admin using IP restrictions on Nginx. The following seems to block wp-admin, but doesn’t block wp-login.php

This is a start as it will stop anyone being able to login from any other IP, as after signing in you are redirected to wp-admin which is restricted. However, they can still get to the sign in form and in theory could still be affected by brute force attacks.

server {
    listen       80;
    server_name  website.com www.website.com dev.website.com;

    location / {
        root           /var/www/html/website.com/;
         index  index.php index.html index.htm;
         try_files $uri $uri/ /index.php?$args;
    }
     location ~ .php$ {
         root           /var/www/html/website.com/;
         fastcgi_pass   127.0.0.1:9000;
         fastcgi_index  index.php;
         fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
         include        fastcgi_params;
     }
     location ~ ^/(wp-admin|wp-login/.php) {
         root           /var/www/html/website.com/;
         index          index.php index.html index.htm;
         allow             123.123.123.123/32;
         deny all;
     }

} 

Related posts

Leave a Reply

4 comments

  1. If you fix your context it might fix this issue. Instead of forward slash do a backslash prior to your .php

    location ~ ^/(wp-admin|wp-login.php) {
                allow 123.123.123.123/32;
                deny all;
    }
    
  2. Not a perfect solution, but I’m now using this:

    server {
        listen       80;
        server_name  website.com www.website.com dev.website.com;
        root         /var/www/html/website.com/;
        error_page 403 404 500 502 503 504 = /server_error.php;
        index index.php index.html index.htm;
    
        location / {
             try_files $uri $uri/ /index.php?$args;
        }
         location = /wp-login.php {
             allow          123.123.123.123/32;
             deny all;
             fastcgi_pass   127.0.0.1:9000;
             fastcgi_index  index.php;
             fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
             include        fastcgi_params;
         }
         location ~ .php$ {
             fastcgi_pass   127.0.0.1:9000;
             fastcgi_index  index.php;
             fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
             include        fastcgi_params;
         }
    
    } 
    

    which will keep everyone out, but doesn’t mask the fact that wp-admin exists. If someone were to navigate to wp-admin, they’re redirected to wp-login.php which is restricted.

    Tidied up a bit too.

  3. I know this is a little old, but your answer helped me and I have improved upon it. So for anyone else seeing this issue which I imagine is actually quite common. For me Nginx was only blocking CSS files.

    I believe the issue is caused by Nginx first seeing its a php file and therefore dealing with it inside location ~ .php$ {} before it gets to location ~ ^/(wp-admin|wp-login.php) {}

    So I did this, firstly above location ~ .php$ {} add:

    location = /wp-login.php{
    
        allow 12.345.6.7; #example IP address
    
        deny all;
    
        fastcgi_index index.php;
        include fastcgi_params;
    
    }
    

    This will block access to wp-login.php which is great, but like you said it doesnt block wp-admin so just follow up by adding the other block below location ~ .php$ {}

    location ~ ^/(wp-admin|wp-login.php) {
    
        allow 12.345.6.7 #example IP address
    
        deny all;
    }
    

    Now, if your not coming from IP 12.345.6.7 then you can’t get access to either wp-admin or wp-login.php

  4. now (2018) WordPress redirects wp-admin automaticaly to wp-login.
    So it’s sufficient to only disallow /wp-login.php wit:

    location = /wp-login.php {
    allow 16.16.12.11
    deny  all;
    }
    

    Just put it after the default “location `.php$” block