Why is nginx accepting requests with a Host header

2019-05-26 07:58发布

I have a site set up this way: nginx as a proxy server, proxying requests tu a gunicorn instance serving a Django site through a UNIX socket.

This is my nginx configuration:

server {
    listen 80;
    server_name api.mysite.com;

    location /static/ {
        alias /webapps/mysite/static/;
        autoindex off;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/webapps/mysite/mysite.sock;
    }

}

Is my understanding that nginx, when receiving a request, matches the Host header against the server_name parameter of the server block and, if it matches, it serves it. However, nginx seems to be trying to serve (passing the request to my Django server) request with a Host header different than api.mysite.com. Django has a setting named ALLOWED_HOSTS (in my case set to ['api.mysite.com']) that performs further checking of the Host header and raises an error if the request Host header doesn't match, which shouldn't happen because nginx is supposedly already filtering this. The thing is that I'm seeing errors raised by Django which look like this:

  • Invalid HTTP_HOST header: '/webapps/mysite/mysite.sock:'. The domain name provided is not valid according to RFC 1034/1035.
  • Invalid HTTP_HOST header: 'testp1.piwo.pila.pl'. You may need to add 'testp1.piwo.pila.pl' to ALLOWED_HOSTS.
  • Invalid HTTP_HOST header: 'xxx.xxx.xxx.xxx' (The real IP of my server). You may need to add 'xxx.xxx.xxx.xxx' to ALLOWED_HOSTS.

A couple of things:

  • I know that the requests are coming through nginx because they show up in nginx logs and it would be impossible anyway to hit directly the gunicorn server because I'm proxying through a UNIX socket and not through HTTP.
  • I know that these requests are coming from a bot looking for free proxies to use, but I don't really care much about that. What I'm really intrigued by is the request with the Host header set to the path on the local filesystem of my gunicorn/nignx UNIX socket.

Any clue?

1条回答
看我几分像从前
2楼-- · 2019-05-26 08:28

Turns out that if nginx doesn't encounter a matching server block, it will send the request to the first server block. So the solution was to set up a default server block that drops every request like this:

server {
    listen 80 default_server;
    return 444;
}
查看更多
登录 后发表回答