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
[USEXFORWARDEDHOST]: https://docs.djangoproject.com/en/1.6/ref/settings/#std:setting-USE_X_FORWARDED_HOST
[HTTP RFC]: https://tools.ietf.org/html/rfc2616