Fix Django Invalid HTTP_HOST header emails
On by Mitesh ShahIt’s been a long time since I deployed a django application on the internet. At first, I had no idea about the features of Django and was running it just like any other flask app. But soon, I came across the wonderful Error Reporting module and I quickly realised how I had been missing something like this in my Flask deployments.
But soon, I started getting a TON of Invalid HTTP_HOST header
. I tried to
take a look into what exactly what happening.
Firstly, I have a couple sites hosted on my server. Some of them are served via
https
and some aren’t. When I took a closer look into the error reports, I
could see that none of them had a request url of earthlyhumans.com (my django
app). They had the request of one of my other websites, but it somehow wasn’t
being caught by their nginx configs.
So I took a look into how nginx choses a configuration for a particular
request. First, it will check if a particular config has a valid listen
directive for the incoming request. If it does, then it moves onto checking the
server_name
directive. If neither happens, it redirects to the default
block.
I already had a default block configured as follows..
server {
listen 80;
return 444;
}
..and yet urls were getting passed onto my Django application.
/etc/nginx/sites-available$ tree
.
|-- default
|-- earthlyhumans.com.conf
|-- example.com.conf
`-- example2.com.conf
0 directories, 4 files
This is how my configuration looked. Now the problem was that why weren’t the requests getting redirected to one of my other applications.
Turns out, the “default” server in nginx is the first server block it reads i.e
sorted alphabetically, unless you have the default_server
option listed in
the listen
directive.
But wait a minute, default
block is still the first listed server block. But
silly me, I hadn’t added a listen block for port 443. So it went ahead and
found the first block with port 443 and matched it with my django server block.
So I simply changed my default config to
server {
listen 80 default_server;
return 444;
}
server {
listen 443 default_server;
server_name _; # This can be omitted.
return 444;
}
special nginx’s non-standard code 444 is returned that closes the connection.
That seemed to have fixed all my issues. You can also explicitly rename default
file to something like 0000-default
which makes sure that it’s the first
config to be loaded.
References: