将 django 站点从 http 升级到 https 后,我不断收到“无效的 HTTP_HOST 标头”错误电子邮件
Posted
技术标签:
【中文标题】将 django 站点从 http 升级到 https 后,我不断收到“无效的 HTTP_HOST 标头”错误电子邮件【英文标题】:I continuously receive `Invalid HTTP_HOST header` error email after I upgrade my django site from http to https 【发布时间】:2018-05-30 12:01:05 【问题描述】:最近,我将我的一个 django 网站从 http 升级到 https。但是,在那之后,我不断收到Invalid HTTP_HOST header
错误邮件,而之前我从未收到过此类邮件。
以下是一些日志消息:
[Django] 错误(外部 IP):无效的 HTTP_HOST 标头:'123.56.221.107'。您可能需要将“123.56.221.107”添加到 ALLOWED_HOSTS。
[Django] 错误(外部 IP):无效的 HTTP_HOST 标头:“www.sgsrec.com”。您可能需要将“www.sgsrec.com”添加到 ALLOWED_HOSTS。
[Django] 错误(外部 IP):无效的 HTTP_HOST 标头:'sgsrec.com'。您可能需要将“sgsrec.com”添加到 ALLOWED_HOSTS。
报告 /apple-app-site-association 无效的 HTTP_HOST 标头:“sgsrec.com”。您可能需要将“sgsrec.com”添加到 ALLOWED_HOSTS。
HTTP_HOST 标头无效:‘www.pythonzh.cn’。您可能需要将“www.pythonzh.cn”添加到 ALLOWED_HOSTS。
报告在 / 无效的 HTTP_HOST 标头:‘www.pythonzh.cn’。您可能需要将“www.pythonzh.cn”添加到 ALLOWED_HOSTS。
请求方法:GET 请求地址:http://www.pythonzh.cn/ Django 版本:1.10.6
[Django] 错误(外部 IP):无效的 HTTP_HOST 标头:'pythonzh.cn'。您可能需要将“pythonzh.cn”添加到 ALLOWED_HOSTS。
奇怪的是,我只更改了我的博客站点www.zmrenwu.com
nginx 配置,但似乎我所有托管在 123.56.221.107 上的站点都受到了影响。
当然,我正确设置了 ALLOWED_HOSTS:
ALLOWED_HOSTS = ['.zmrenwu.com']
ALLOWED_HOSTS = ['.sgsrec.com']
ALLOWED_HOSTS = ['.pythonzh.cn']
我的博客站点www.zmrenwu.com
的nginx配置:
server
charset utf-8;
server_name zmrenwu.com www.zmrenwu.com;
listen 80;
return 301 https://www.zmrenwu.com$request_uri;
server
charset utf-8;
server_name zmrenwu.com;
listen 443;
ssl on;
ssl_certificate /etc/ssl/1_www.zmrenwu.com_bundle.crt;
ssl_certificate_key /etc/ssl/2_www.zmrenwu.com.key;
return 301 https://www.zmrenwu.com$request_uri;
server
charset utf-8;
listen 443;
server_name www.zmrenwu.com;
ssl on;
ssl_certificate /etc/ssl/1_www.zmrenwu.com_bundle.crt;
ssl_certificate_key /etc/ssl/2_www.zmrenwu.com.key;
location /static
alias /home/yangxg/sites/zmrenwu.com/blogproject/static;
location /media
alias /home/yangxg/sites/zmrenwu.com/blogproject/media;
location /
proxy_set_header Host $host;
proxy_pass http://unix:/tmp/zmrenwu.com.socket;
为什么会这样?我该如何解决这个问题?
【问题讨论】:
【参考方案1】:你需要在一个块中添加
location /
此条件(对于非您的域请求):
if ( $host !~* ^(yourdomain.com|www.yourdomain.com)$ )
return 444;
和
sudo service nginx reload
【讨论】:
@solarissmoke 如果在位置上下文中,唯一可以在内部完成的 100% 安全的事情是:return ...;
rewrite ... last
在您的回答中,块 2 应该在块 1 内吗?还是分别需要两个块?我只有第 2 块,但它似乎不能单独工作。请澄清。
我已经有一个带有 proxy_pass 指令的位置块。我也有多个位置块(静态、媒体等)。目前我的块 2 在位置块之外,它似乎不起作用。【参考方案2】:
在我看来,按照其他答案中的建议禁用 DisallowedHost
主机警告并不是正确的解决方案。 Django 给你这些警告是有原因的 - 你最好在这些请求到达 Django 之前阻止它们。
您在 nginx 配置中创建了一个新的服务器块。因为它是您定义的唯一 HTTPS 服务器,所以它成为该端口的默认服务器。来自documentation:
default_server
参数(如果存在)将导致服务器成为指定address:port
对的默认服务器。如果所有指令都没有default_server
参数,那么第一个具有address:port
对的服务器将是该对的默认服务器。
这解释了为什么您会突然看到所有这些无效的主机错误。现在尝试通过 HTTPS 连接到您的服务器的任何机器人最终都将使用此默认服务器。因为许多机器人将使用假主机名或仅使用您的服务器 IP(两者都不在 ALLOWED_HOSTS
中),这会导致 Django 中的警告。
那么解决方法是什么?您可以创建一个单独的服务器块来处理所有此类无效请求:
server
listen 443 ssl default_server;
server_name _;
return 444;
444
是nginx对disconnect invalid requests使用的特殊响应状态。
添加此块后,它将用于所有与您要响应的主机标头不匹配的请求,并且任何尝试与无效主机连接的东西都将无法连接。
同时,Django 将停止查看对无效主机的请求。
【讨论】:
_
for server_name
有什么作用?
_ 只是一个无效值,永远不会在真实主机名上触发。
请注意,如果 nginx 在 ALB 后面,那么您也可能会丢弃可能影响正常运行时间的运行状况检查请求【参考方案3】:
这可能是因为可能有正在运行的机器人脚本针对您的服务器使用不同的 HTTP_HOST 标头(这很常见)。在 django 中,您已将 Allowed Hosts 设置为特定主机。因此,如果出现与“允许的主机”中指定的主机头不同的主机头,那么 django 将给出 400 错误。
默认情况下,django 记录器被配置为在每个错误时发送邮件。要停止接收邮件,您需要在 django 中配置记录器并添加
以下记录器
'django.security.DisallowedHost':
'handlers': ['null'],
'propagate': False,
,
参考https://www.calazan.com/how-to-disable-the-invalid-http_host-header-emails-in-django/
【讨论】:
谢谢!但是为什么在升级到 https 之前,我没有收到任何此类错误电子邮件?这只是巧合? 这只会禁用通知,但不会消除原因。您仍然会收到这些错误,但不会被报告。解决方案应重新限制此类请求以到达 django 应用程序。以上是关于将 django 站点从 http 升级到 https 后,我不断收到“无效的 HTTP_HOST 标头”错误电子邮件的主要内容,如果未能解决你的问题,请参考以下文章
老板说“把系统升级到https”,我用一个脚本实现了,而且永久免费!