Nginx conditional "allow" directive based on query parameter

Viewed 43

I have a list of IP addresses to whitelist in my Nginx configuration. But the requirement is that it should be applied only when the key=123 query parameter specified. I already know that if directive is not applicable for my case due to this. So I tried to use conditional includes like this:

map $arg_key $allowed_ips_config_file {
    123 "includes/1.conf";
    default "includes/2.conf";
}

location /some/path {
    set $backend        http://localhost:8080;
    proxy_pass          $backend;

    proxy_set_header    Host $http_host;
    proxy_buffering     off;
    proxy_read_timeout  15m;
    expires             -1;

    include $allowed_ips_config_file;
}

includes/1.conf:

allow <my-ip-range>;
deny all;

includes/2.conf:

allow all;

It didn't work either because apparently Nginx does not allow variables in include directive.

I found one option how to solve this problem but it doesn't seem right to me. Is there a right way to do this?

1 Answers

So I spent some time trying to figure this out, but ended up with the approach from the link I posted above. Here is a completely working solution:

./docker-compose.yml:

version: '3'
services:
  webserver:
    image: openresty/openresty:1.11.2.3-xenial
    container_name: webserver
    restart: unless-stopped
    tty: true
    ports:
      - "80:80"
    volumes:
      - ./:/var/www
      - ./nginx/conf.d/default.conf:/usr/local/openresty/nginx/conf/nginx.conf

./nginx/conf.d/default.conf:

worker_processes  1;

events {
    worker_connections  1024;
}


http {
  server {
      listen 80;
      root /var/www/public;

      location / {
          root   html;
          index  index.html index.htm;
      }

      location /api {
          error_page 418 = @queryone;
          error_page 419 = @querytwo;

          if ( $arg_key = "123" ) { return 418; }
          if ( $arg_key != "123" ) { return 419; }
      }

      location @queryone {
          allow <YOUR_IP_RANGE_GOES_HERE>;
          deny all;
          echo "1";
      }

      location @querytwo {
          echo "2";
      }
  }
}

To check:

docker-compose up -d
curl "localhost/api?key=123"
curl "localhost/api?key=124"
Related