nginx Django错误:HTTP_HOST标头无效:u“/运行/我的项目名称/gunicorn.sock:”

q0qdq0h2  于 2023-03-17  发布在  Nginx
关注(0)|答案(3)|浏览(159)
  • 我知道在SO上有很多这样的问题,但似乎没有一个能回答我的特定问题。*

我知道Django的ALLOWED_HOSTS值会阻止任何对我IP上的80端口的请求,如果没有正确的Host:值,Django会给我发邮件。我也知道slick Nginx hack可以解决这个问题,但我正试图了解这样一个请求的性质,并确定这是否是一个需要担心的安全问题。
这样的请求是有意义的:
[Django]错误:HTTP_HOST标头无效:“203.0.113.1”。您可能需要将“203.0.113.1”添加到“允许主机”中。
但有一件事让我有点抓狂:
[Django]错误:HTTP_HOST标头无效:u“/运行/我的项目名称/gunicorn.sock:'.
这是否意味着请求者发送了Host: /run/my_project_name/gunicorn.sock到服务器?如果是这样,他们是如何得到我的.sock文件的路径名的?是我的服务器不知何故泄漏了这些信息吗?
另外,当我运行Django 1.6.5时,我完全不明白为什么我会收到这些邮件,因为this ticket已经被标记为修复了一段时间。
有人能告诉我我错过了什么吗?
这是我的settings.LOGGING变量:

{
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {'()': 'django.utils.log.RequireDebugFalse'}
    },
    'formatters': {
        'simple': {'format': '%(levelname)s %(message)s'},
        'verbose': {'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'}
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
            'level': 'DEBUG'
        },
        'mail_admins': {
            'class': 'django.utils.log.AdminEmailHandler',
            'filters': ['require_debug_false'],
            'level': 'ERROR'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True
        },
        'my_project_name': {
            'handlers': ['console'], 
            'level': 'DEBUG'
        }
    },
    'version': 1
}

下面是我的nginx配置:

worker_processes 1;
pid /run/nginx.pid;
error_log /var/log/myprojectname/nginx.error.log debug;
events {
}
http {
  include mime.types;
  default_type application/octet-stream;
  access_log /var/log/myprojectname/nginx.access.log combined;
  sendfile on;
  gzip on;
  gzip_http_version 1.0;
  gzip_proxied any;
  gzip_min_length 500;
  gzip_disable "MSIE [1-6]\.";
  gzip_types text/plain text/html text/xml text/css
             text/comma-separated-values
             text/javascript application/x-javascript
             application/atom+xml;
  upstream app_server {
    server unix:/run/myprojectname/gunicorn.sock fail_timeout=0;
  }
  server {
    listen 80 default;
    listen [::]:80 default;
    client_max_body_size 4G;
    server_name myprojectname.mydomain.tld;
    keepalive_timeout 5;
    root /var/www/myprojectname;
    location / {
      try_files $uri @proxy_to_app;
    }
    location @proxy_to_app {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;
      proxy_redirect off;
      proxy_pass http://app_server;
    }
    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /tmp;
    }
  }
}

最后,我在我的nginx访问日志中发现了这个,它对应于抱怨/run/myprojectname/gunicorn.sock是无效HTTP_HOST头的电子邮件。*
当然,这一切都在一条线上:

2014/09/05 20:38:56 [info] 12501#0: *513 epoll_wait() reported that client
prematurely closed connection, so upstream connection is closed too while sending
request to upstream, client: 54.84.192.68, server: myproject.mydomain.tld, request:
"HEAD / HTTP/1.0", upstream: "http://unix:/run/myprojectname/gunicorn.sock:/"

显然我还是不知道这是什么意思:-(

**更新#1:添加了我的settings.LOGGING *
**更新#2:添加了我的nginx配置 *
**更新#3:从我的nginx日志中添加了一个有趣的行 *
**更新编号4:更新了我的nginx配置 *

3z6pesqy

3z6pesqy1#

好像

proxy_set_header Host $http_host

should be changed

proxy_set_header Host $host

server_name应该被设置为访问服务器的地址,如果你想让它捕获所有内容,你应该使用server_name www.domainname.com ""(doc在这里)。
我不确定,但我认为如果客户端没有发送Host:头文件,就会发生您所看到的情况。由于nginx没有接收到Host:头文件,因此没有Host:头文件传递给gunicorn。此时,我认为gunicorn将Host:作为套接字路径填充并告诉Django,使用$host并在nginx中设置server_name应该可以确保Host:正确地传递给gunicorn并解决这个问题。
至于电子邮件,根据您链接的票证中的提交,看起来仍在向禁用的主机发送电子邮件。添加到文档中的还有禁用正在发送的电子邮件的建议方法:

'loggers': {
        'django.security.DisallowedHost': {
        'handlers': ['null'],
        'propagate': False,
        }
    },
vdzxcuhz

vdzxcuhz2#

我遇到过一些评论,建议抑制电子邮件不是一个好主意,因为它不能直接解决这个问题。我发现最有效的解决方案是添加以下到您的nginx设置:

server {

    ...

    ## Deny illegal Host headers
    if ($host !~* ^(mydomain.com|www.mydomain.com)$ ) {
        return 444;
    }
}

如需了解更多信息:https://snakeycode.wordpress.com/2015/05/31/django-error-invalid-http_host-header/
博客文章提到了这个问题。

xdnvmnnf

xdnvmnnf3#

我知道这是一个老问题,但这个问题今天才发生在我身上。Django docs推荐的解决方案是在你的nginx配置中添加一个“catch all”nginx服务器:

server {
    listen 80 default_server;
    return 444;
}

nginx的官方文档推荐了同样的解决方案,给予了一些语法上的细微差别。
这样的话,请求不会发送到django,当nginx收到一个格式错误的请求时,连接会立即关闭。

相关问题