nginx Block IP based on URI in one 'location'

Solution 1:

Like coredump said, no, use multiple locations.

But it is possible to make the contents of the location blocks less repetitive. The key here is a named location block which contains the root and proxy_... directives.

For example:

location / {
  try_files $uri @proxy;
}
location ~ /(abc|def|ghi) {
  allow 10.0.0.0/8;
  allow 1.2.3.4;
  deny all;

  try_files $uri @proxy;
}
location @proxy {
  root  /var/www/docs;
  proxy_pass  http://backend;
  proxy_buffering     on;
  proxy_buffer_size   64k;
  proxy_buffers       256   64k;
}

And probably even better would be to place the root directive outside all the location blocks.

Solution 2:

First you have to define a variable that will hold your IP filters. This goes into the http section of the nginx config:

map $remote_addr (or $http_x_forwarded_for if behind a proxy) $allowed {
        default deny;
        ~\s*111.222.333.444$ allow;
        ~\s*333.444.555.*$   allow;
    }

then in the server section you write the if construct and filter the access location by the contents of the variable $allowed:

location / {
        if ( $allowed = "deny" ) { return 403; }
        #...
    }

Solution 3:

Usually in such cases can help "nested locations" ...

location / {
   root /var/www/docs;
   allow all;

   location /admin {
       deny 1.2.3.4;
   }

}

... but not all directives inherited in nested locations. Sadly, but exactly proxy_pass, fastcgi_pass and similar are not inherited... So solution proposed earlier (with @namedlocation) is correct in this case. You can also use a directive include for "proxy_pass block", of course.

Solution 4:

No. Use multiple locations, it may look ugly but you will end with less chance of if craziness.

Also remember that nginx processes first the regex matches and if none matches it tries the most specific literal location, being location / kind of a catch all location. Knowing that you can maybe diminish the number of locations you need. Take a look at this doc to see how requests are processed.