为什么 nginx 接受主机标头与 server_name 不匹配的请求?

san*_*blo 5 unix django proxy nginx gunicorn

我有一个这样设置的站点:nginx 作为代理服务器,通过 UNIX 套接字代理请求一个为 Django 站点提供服务的 gunicorn 实例。

这是我的 nginx 配置:

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;
    }
Run Code Online (Sandbox Code Playgroud)

}

我的理解是 nginx 在接收请求时将Host标头与服务器块的 server_name 参数匹配,如果匹配,则为其提供服务。但是,nginx 似乎正在尝试使用与Hostapi.mysite.com 不同的标头来服务(将请求传递到我的 Django 服务器)请求。Django 有一个名为ALLOWED_HOSTS (在我的情况下设置为['api.mysite.com'])的设置,它执行对Host标头的进一步检查,并在请求Host标头不匹配时引发错误,这不应该发生,因为 nginx 应该已经过滤了它。问题是我看到 Django 引发的错误如下所示:

  • 无效的 HTTP_HOST 标头:'/webapps/ mysite/ mysite.sock:'。根据 RFC 1034/1035,提供的域名无效。
  • 无效的 HTTP_HOST 标头:'testp1.piwo.pila.pl'。您可能需要将“testp1.piwo.pila.pl”添加到 ALLOWED_HOSTS。
  • 无效的 HTTP_HOST 标头:'xxx.xxx.xxx.xxx' (我服务器的真实 IP)。您可能需要将“xxx.xxx.xxx.xxx”添加到 ALLOWED_HOSTS。

几件事:

  • 我知道请求是通过 nginx 发出的,因为它们出现在 nginx 日志中,无论如何都不可能直接访问 gunicorn 服务器,因为我通过 UNIX 套接字而不是通过 HTTP 进行代理。
  • 我知道这些请求来自一个寻找免费代理的机器人,但我不太关心这个。我真正感兴趣的是请求Host头设置为我的 gunicorn/nignx UNIX 套接字的本地文件系统上的路径。

有什么线索吗?

san*_*blo 3

事实证明,如果 nginx 没有遇到匹配的服务器块,它会将请求发送到第一个服务器块。因此,解决方案是设置一个默认服务器块来删除每个请求,如下所示:

server {
    listen 80 default_server;
    return 444;
}
Run Code Online (Sandbox Code Playgroud)