Recently I’ve noticed some errors in relation to the above which are causing concern to whether actionable data is being retrieved.
Here’s what I get on a cURL:
$ curl --verbose -k --header 'Host: /run/gunicorn.sock' 'https://www.example.com'
* Trying IP_ADDRESS:443...
* Connected to www.example.com (IP_ADDRESS) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=example.com
* start date: Sep 2 23:25:50 2020 GMT
* expire date: Dec 1 23:25:50 2020 GMT
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x66e0f0)
> GET / HTTP/2
> Host: /run/gunicorn.sock
> user-agent: curl/7.71.1
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 400
< server: nginx/1.16.1
< date: Sat, 12 Sep 2020 14:09:38 GMT
< content-type: text/html
< content-length: 157
<
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/1.16.1</center>
</body>
</html>
* Connection #0 to host example.com left intact```
Here’s my Nginx conf:
server {
server_name www.example.com "";
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/username/example.com;
}
if ($host !~* ^(example.com|www.example.com)$){
return 444;
}
location / {
include proxy_params;
proxy_set_header Host $host;
proxy_pass http://unix:/run/gunicorn.sock;
}
listen 443 ssl http2;
# *Cerbot managed files*
}
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name www.example.com "";
return 404; # managed by Certbot
}
I’ve managed to get it to reject the majority of these type of requests (where host headers are IP addresses or words) but it seems that this one keeps getting through. Is there any additional information / fix for these type of attacks and whether I should be concerned to a genuine security issue?
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hi there @mspe,
As /run/gunicorn.sock is not really a valid host, the request is not really being handled and it is not reaching the Nginx server block, so I believe that this is not really a security issue.
What I would usually do, is to set up a default Nginx server block which drops any request that do not match my server block hosts:
server {
listen 80 default_server;
return 444;
}
Though this would still result in a 400 Bad Request error if you pass an invalid host in the request header.
Hope that this helps! Regards, Bobby
Heya,
here is more information on this topic in hopes that someone might find it helpful
The cURL request you’re performing seems unusual since it includes the Unix socket in the ‘Host’ header. Typically, the ‘Host’ header should contain the domain name, not a path to a Unix socket. The error “400 Bad Request” from Nginx is appropriate because the ‘Host’ header value is invalid for an HTTP request.
Your Nginx configuration is generally correct for serving a site via Gunicorn using a Unix socket, but let’s address your concerns:
The ‘Host’ header is expected to be a domain name, not a file path. If you’re receiving requests with invalid ‘Host’ headers, you can tighten your Nginx configuration to handle these better.
Your current configuration has this check:
if ($host !~* ^(example.com|www.example.com)$){
return 444;
}
This is good for rejecting requests with unexpected ‘Host’ values. However, the if directive in Nginx is generally discouraged due to unpredictable behavior. Instead, you can rely on server_name and default server blocks to handle unrecognized domains:
server {
listen 80 default_server;
listen 443 ssl http2 default_server;
server_name _;
return 444;
}
This configuration will drop requests that don’t match any known server block.
The 400 errors you’re seeing in your logs for requests with an invalid ‘Host’ header are not necessarily indicative of a security issue. It’s common for web servers to receive malformed or malicious requests. As long as your server is correctly rejecting these requests (as it seems to be), this behavior is part of normal internet “background noise.”
However, ensure you follow security best practices:
For testing, you can make a more standard cURL request, ensuring the ‘Host’ header is a domain, not a socket path:
curl --verbose -k https://www.example.com
Ensure your SSL certificates are correctly set up for HTTPS connections. Since you’re using Certbot, it should handle the configuration and renewal of these certificates.
Your Nginx setup appears to be generally fine, but it’s always good to remain vigilant and review your configurations and logs regularly. The errors you’re seeing are likely normal and not a cause for concern as long as your server responds to them appropriately.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.