部署Nginx+Gunicorn+Django遇DisallowedHost及400错误求助
Django部署Nginx+Gunicorn遭遇DisallowedHost与400错误排查方案
问题背景
首次部署Django项目likarnet到DigitalOcean Ubuntu服务器,采用Nginx+Gunicorn架构,已完成域名likarnet.com绑定公网IP及SSL配置,但持续出现DisallowedHost异常、400 Bad Request响应及Invalid HTTP_HOST header错误,常规方案尝试后无效。
环境版本
- Python 3.12
- Django 5.0.6
相关配置文件
1. Nginx配置(/etc/nginx/sites-available/likarnet)
server { listen 80 default_server; listen [::]:80 default_server; server_name likarnet.com www.likarnet.com; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/likarnet/website/likarnet; } location /media/ { root /home/likarnet/website/likarnet; } location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $server_name; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Real-IP $remote_addr; proxy_redirect off; proxy_pass http://unix:/run/gunicorn.sock; } }
也曾尝试替换为默认的include proxy_params;配置。
2. Gunicorn服务配置(/etc/systemd/system/gunicorn.service)
[Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target [Service] User=likarnet Group=sudo WorkingDirectory=/home/likarnet/website/likarnet ExecStart=/home/likarnet/venv/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind unix:/run/gunicorn.sock \ --chdir=/home/likarnet/website/likarnet \ likarnet.wsgi:application [Install] WantedBy=multi-user.target
测试结果
- 运行
python3 manage.py runserver 127.0.0.1:8000或0.0.0.0:8000后,执行curl -v localhost:8000返回301重定向,终端打印的ALLOWED_HOSTS包含['likarnet.com', '.likarnet.com', '64.225.77.248', '127.0.0.1', 'localhost'] - 执行
curl --unix-socket /run/gunicorn.sock localhost返回400 Bad Request页面 - 浏览器访问
likarnet.com显示ERR_CONNECTION_REFUSED - 执行
curl -v localhost:80返回400 Bad Request响应
错误日志回溯
ERROR 2024-06-22 06:26:47,521 /home/likarnet/venv/lib/python3.12/site-packages/django/core/handlers/exception.py 124 Func: response_for_exception Task: None Process: 1274 MainProcess Thread: 133201422356608 MainThread Message: Invalid HTTP_HOST header: 'localhost'. You may need to add 'localhost' to ALLOWED_HOSTS. StackInfo: None Traceback (most recent call last): File "/home/likarnet/venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "/home/likarnet/venv/lib/python3.12/site-packages/django/utils/deprecation.py", line 133, in __call__ response = self.process_request(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/likarnet/venv/lib/python3.12/site-packages/django/middleware/common.py", line 48, in process_request host = request.get_host() ^^^^^^^^^^^^^^^^^^ File "/home/likarnet/venv/lib/python3.12/site-packages/django/http/request.py", line 162, in get_host raise DisallowedHost(msg) django.core.exceptions.DisallowedHost: Invalid HTTP_HOST header: 'localhost'. You may need to add 'localhost' to ALLOWED_HOSTS.
排查方向与解决方案
确认ALLOWED_HOSTS配置生效
- 检查生产环境
settings.py,确保ALLOWED_HOSTS包含localhost、127.0.0.1、likarnet.com、www.likarnet.com及服务器公网IP。注意:Django 5.0+已废弃.likarnet.com通配符格式,需改为['likarnet.com', 'www.likarnet.com'],或用*临时测试(生产环境禁用)。 - 重启Gunicorn服务:
sudo systemctl restart gunicorn,避免配置未加载。
- 检查生产环境
修正Nginx代理头配置
- 当前
proxy_set_header Host $host;会传递请求的原始Host头,若直接访问localhost:80会导致Host为localhost,建议替换为proxy_set_header Host $server_name;,强制传递配置的域名作为Host头,确保Django收到的Host在ALLOWED_HOSTS列表内。 - 重启Nginx并验证配置:
sudo nginx -t&&sudo systemctl restart nginx。
- 当前
检查Gunicorn Socket权限
- 执行
ls -l /run/gunicorn.sock查看权限,确保Nginx用户(通常为www-data)可读写。若权限不足,可修改Gunicorn配置添加--user www-data --group www-data,或临时调整socket权限:sudo chmod 777 /run/gunicorn.sock(生产环境建议用更严格的权限)。
- 执行
验证SSL与防火墙配置
- 检查是否存在监听443端口的Nginx server块,确保SSL证书配置正确。若SSL配置缺失或错误,会导致外部访问被拒绝。
- 检查防火墙状态:
sudo ufw status,确保80、443端口已开放,若未开放执行:sudo ufw allow 80/tcp&&sudo ufw allow 443/tcp。
直接测试Gunicorn的Host处理
- 绑定TCP端口启动Gunicorn:
/home/likarnet/venv/bin/gunicorn --bind 127.0.0.1:8001 likarnet.wsgi:application,然后执行curl -H "Host: likarnet.com" localhost:8001,若返回正常,说明问题出在Nginx代理或Socket配置。
- 绑定TCP端口启动Gunicorn:
内容的提问来源于stack exchange,提问作者Mykhaylo Chornenkyy
相关产品推荐
相关产品推荐

