6

I am trying to restrict access to the admin section of my django app by using simple host-based access control in nginx. Unfortunately nginx does not seem to abide by the configuration request:

this is my setting for this particular section in nginx:

# gunicorn setup
location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 }


 location /admin/ { # restrict access to admin section
    allow 192.168.0.1;
    deny all;
 }

This does still block my ip 192.168.0.1. What am I doing wrong? Is there another way to block access to the /admin/ section of a django app?

jcuot
  • 935
  • 9
  • 24

2 Answers2

19

I found a solution to this problem by replacing the /admin/ location with the following:

location ^~ /admin/ { # restrict access to admin section
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    allow 192.168.0.1;
    deny all;
}

I hope this will save someone some long searches on the internet. I would appreciate answers offering a better solution.

jcuot
  • 935
  • 9
  • 24
  • 1
    Is there also a way to configure that on gunicorn level? I'm asking, because I'm deploying my application with Docker and don't want to have a dependency to my nginx-proxy container. I wanna clearly separate both from each other that's why I would like to configure that on gunicorn web server level. – headbanger Dec 27 '19 at 13:37
0

If you are using an AWS Load Balancer
Then you will run into an issue where the IP being passed is not the client IP but rather the IP of the LB.

You will need a different blocking mechanism here. Do the following precisely.

Add the following to the top level http block:

    # The X-Forwarded-For is the client IP which is what we need insted of the
# load balancer IP
real_ip_header X-Forwarded-For;
set_real_ip_from 10.0.0.0/8;

log_format main '$remote_addr - $remote_user $time_local '
                '"$request" $status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"' ;

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

Add the following to the server block. replace that x.x.x.x with your VPN or whitelisted IP. For example: ?44\.231\.29\.79?$

# Only allow access to admin panel through VPN IP
location ^~ /admin/ { # restrict access to admin section
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    set $allow false;
    if ($http_x_forwarded_for ~ " ?x\.x\.x\.x?$") {
        set $allow true;
    }

    if ($http_x_forward_for ~ " ?x\.x\.x\.x$") {
        set $allow false;
    }

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

Answer taken from AWS forum https://forums.aws.amazon.com/thread.jspa?threadID=62474#

dipole_moment
  • 5,266
  • 4
  • 39
  • 55