Here’s how you can easily protect Django admin by blocking unwanted IP addresses using NGINX and Gunicorn when behind an AWS Load Balancer.
Django Admin
The Django Admin app is great. This included tool allows you easily set up a password-protected section of your website, allowing administrators to manage site data with a simple and intuitive interface. Now, the password protection may be enough security for what you need, especially when delivered through HTTPS. But, it’s also nice to be able to prevent global access to that section completely, denying hackers a way to use techniques like brute-force attacks to gain access to your data.
Blocking by IP is easily done in both Apache and NGINX with some simple allow/deny rules. But when your Django site is running on an EC2 instance behind an AWS Elastic Load Balancer (ELB) at Amazon, you have to handle blocking a bit differently. The IP that is sent to your server is actually the ELB’s IP, not the remote client’s address. The load balancer actually stores the client IP in the X-Forwarded-For request header, which you can pick off and use in the NGINX site configuration.
NGINX Configuration
Here’s a configuration file snippet for NGINX showing how to protect Django admin by blocking the /admin/ subdirectory from any unauthorized IP addresses when proxying to Gunicorn to serve up your Django site:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# set up an upstream definition that proxies the requests to Gunicorn upstream your_server{ server unix:/path/to/your/gunicorn.sock fail_timeout=0; } server { listen 80; server_name yourwebsite.com www.yourwebsite.com; ## prevent admin access by IP ## set $allow false; # check http_x_forwarded_for to get the actual IP if ($http_x_forwarded_for ~ "12\.34\.5\.67") { # matches an allowed IP, so set variable to true set $allow true; } # the admin subdirectory location /admin/ { # set the proxy to pass through to your upstream server (defined above) proxy_pass http://your_server; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # if allow variable is still false, deny access if ($allow = false){ return 403;} } ... the rest of the config ... } |