Nginx Location Block Access List and 'X-Forwarded-For'

6.9k Views Asked by At

I have a few wordpress sites on a Load Balanced Nginx Cluster. I wish to block access to /wp-admin and /wp-login.php on these. The client is not willing to use a plugin such as Wordfence to achieve this (understandably).

The Load Balancers forward the real client IP within X-Forwarded-For, and this is present within Nginx, as I currently use it in my main log format with "$http_x_forwarded_for".

This is my current location block:

   location ~ ^/(wp-admin|wp-login.php) {

     real_ip_header X-Forwarded-For;

     try_files $uri $uri/ /index.php?$args;
     index index.html index.htm index.php;

     root           /var/www/vhosts/domain.com/html;
     fastcgi_pass   127.0.0.1:9000;
     fastcgi_index  index.php;
     fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
     include        fastcgi_params;

     allow 1.1.1.1;
     allow 2.2.2.2;
     allow 3.3.3.3;
     #allow 10.10.85.0/24;
     deny all;
   }

As you can see, I use "real_ip_header X-Forwarded-For;" to declare what the real ip should be. But this does not work. With the above in place, ALL requests to there are blocked. If I uncomment the private 10.10.85.0/24 subnet (which is the private network that traffic is delivered on FROM the load balancers), then access to the locations is granted for EVERYONE.

I do have the realip module compiled in Nginx, as can be seen here:

[root@STR-MAI-ORDS1 conf.d]# 2>&1 nginx -V | tr -- - '\n' | grep http_realip_module
http_realip_module
[root@STR-MAI-ORDS1 conf.d]#

In my log files, I can see the real public IP being printed to log through use of X-Forwarded-For, but the same does not work for this location block realip, and I'm not sure why.

If it matters, the environment looks like this:

  • pfSense FW (2 node HA)
  • Zevenet Load Balancer (2 node HA)
  • CentOS 6.x Web Server (3 node cluster)

The web stack is:

  • Nginx v1.12.0
  • PHP-FPM v7.0.20 (fastcgi)

Any advice on what I'm doing wrong would be great. Thanks.

2

There are 2 best solutions below

1
On

You can create a config file for multiple blockings as below.

modify ngnix config file

vi /usr/local/nginx/conf/nginx.conf

include new config file for blocking the IPs inside nginx.conf

include blockips.conf;

save the ngnix config file and create the new file

vi blockips.conf

add your blacklisted IPs

deny 1.2.3.4;

or subnet blocking

deny 91.212.45.0/24;

for more information see nginx Blocking IP and for subnet

0
On

Turns out "set_real_ip_from" within Nginx is not optional... Even though I was correctly setting the "real_ip_header" to "X-Forwarded-For form the LoadBalancers, Nginx was completely refusing to do so because it doesn't (by default) trust the LB as a source that can set the real IP.

The fix was to include the following within my location block:

set_real_ip_from 10.10.85.0/24;
real_ip_header X-Forwarded-For;

Then Nginx trusts the LB (which is within that subnet) and sets the real-ip to that.