Skip to content

Commit c36e9d4

Browse files
author
Stuart MacKay
committed
Stop invalid host header errors being raised by Django
When a client uses the IP address instead of the domain name Django will raise an `Invalid HTTP_HOST header` error since the IP address is not listed in the ALLOWED_HOSTS setting. This situation occurs most commonly with bots probing the site for security holes. If you log Django errors using Sentry then a constant stream of these errors will be reported. At best they are a distraction. The solution is for nginx to terminate the connection immediately so the request never reaches Django. This is done simply by matching the host header with the sites IP address and raising the HTTP error 444 which is unique to nginx and instructs the server to close the connection immediately. Nothing is returned to the client so it effectively gets a status code of 0. The problem and the solution is described clearly in the following post: https://www.borfast.com/blog/2020/07/06/invalid-http_host-header-errors-in-django-and-nginx/ There a related problem that triggers same Invalid HTTP_HOST header error when the client does not set the HOST header at all. This is discussed and a solution given in this Stack Overflow question (the URL was truncated but is still valid) https://stackoverflow.com/questions/25370868/ The test for using an IP address instead of a domain name was added to post 80 and 443. It should have been possible to let the redirect from HTTP to HTTPS complete and have test in a single location however since the intent of the client is generally malicious it didn't seem right to waste more energy than was necessary, hence the duplication of the check.
1 parent debc7cf commit c36e9d4

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

roles/nginx/templates/django_default_project.j2

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ server {
1010
listen 80;
1111
server_name {{ nginx_server_name }};
1212
server_tokens off;
13+
14+
# Terminate the request immediately if a request uses the IP address.
15+
# This stops Invalid HTTP_HOST header exceptions being raised by Django.
16+
17+
if ($host !~* ^({{ nginx_server_name }})$ ) {
18+
return 444;
19+
}
20+
1321
return 301 https://$server_name$request_uri;
1422
}
1523

@@ -31,6 +39,13 @@ server {
3139
ssl_dhparam /etc/ssl/certs/dhparams.pem;
3240
{% endif %}
3341

42+
# Terminate the request immediately if a request uses the IP address.
43+
# This stops Invalid HTTP_HOST header exceptions being raised by Django.
44+
45+
if ($host !~* ^({{ nginx_server_name }})$ ) {
46+
return 444;
47+
}
48+
3449
# Prevent MIME type sniffing for security
3550
add_header X-Content-Type-Options "nosniff";
3651

@@ -95,7 +110,7 @@ server {
95110

96111
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
97112
proxy_set_header X-Forwarded-Proto https;
98-
proxy_set_header Host $http_host;
113+
proxy_set_header Host $host;
99114
proxy_redirect off;
100115

101116
# Try to serve static files from nginx, no point in making an

0 commit comments

Comments
 (0)