How to deny access to resources based on X-forwarded-for headers

Solution 1:

Use the RealIP module to honour the value of the X-Forwarded-For header. Set set_real_ip_from to the IP address of the reverse proxy (the current value of $remote_addr).

For example:

server {
    ...
    real_ip_header X-Forwarded-For;
    set_real_ip_from 10.1.2.3;
    ...
}

You should now be able to use $remote_addr and allow/deny directives using the true IP address of the client. See this document for more.

Solution 2:

Richard's answer already contained the information on how to best get the real IP address to nginx.

Meanwhile, what comes to the question of specifying IP ranges, you can use http://nginx.org/en/docs/http/ngx_http_geo_module.html.

The geo module works like the map module, that is, a variable gets assigned values depending on the value of IP address.

An example:

geo $allow {
    default 0;
    192.168.168.0/24 1;
}

server {
    real_ip_header X-Forwarded-For;
    set_real_ip_from 10.1.2.3;

    if ($allow = 0) {
        return 403;
    }
}

Here we assign the geo map, where the default value for $allow is 0. If the IP address is in subnet 192.168.168.0/24, then $allow will get value 1, and the request is allowed.

You can have as many lines in the geo block as you need to define your IP ranges.

Solution 3:

Got these working for me.

geo $remote_addr $giveaccess {
      proxy 172.0.0.0/8; <-- Private IP range here
      default 0;
      11.22.33.44 1; <-- Allowed IP here
    }


server{
##
    location ^~ /secure_url_here {
        if ($giveaccess = 0){
          return 403; 
        }
        try_files $uri $uri/ /index.php?$args; <-- Add this line specific for your CMS, if required.
    }

Ref: http://nginx.org/en/docs/http/ngx_http_geo_module.html