Last Updated: February 25, 2016
·
1.173K
· gaqzi

How to make Django believe directly hitting the IP is a certain host in nginx

Or how to make Django show the correct page for Amazon's ELB (Elastic Load Balancer).

In Django 1.5 the [ALLOWED_HOSTS] variable was introduced which was intended to remove an attack vector available if the host is being accessed from an undefined domain. Which is a good thing, it means that if someone is hitting your website through a proxy that makes all the requests look like it's coming from mysite.scammer.ru it'll be declined.

The general solution most people employed is to set a Host header in your proxy request á:

server {
    listen 80;
    listen 9040 default;

    server_name www.example.com;

    location / {
                include proxy_params;
        proxy_set_header Host www.example.com;
        proxy_pass http://localhost:8040;
    }
}

With an upgrade to a never version of nginx I noticed that proxy_set_header Host just keeps appending hosts. Which didn't work, from what I can tell from skimming the [HTTP RFC] Host isn't supposed to be a multi-value field.

Luckily Django got a variable [USEXFORWARDED_HOST] which will look for the host to check against in the HTTP header X-Forwarded-Host if set to True.

So my new working configuration looks like this:

server {
    listen 80;
    listen 9040 default;

    server_name www.example.com;

    location / {
                include proxy_params;
        proxy_set_header X-Forwarded-Host www.example.com;
        proxy_pass http://localhost:8040;
    }
}

[ALLOWEDHOSTS]: https://docs.djangoproject.com/en/1.6/ref/settings/#allowed-hosts
[USE
XFORWARDEDHOST]: https://docs.djangoproject.com/en/1.6/ref/settings/#std:setting-USE_X_FORWARDED_HOST
[HTTP RFC]: https://tools.ietf.org/html/rfc2616