域名访问Nginx报400 Bad Request,IP访问正常的问题求助
访问http://exhibit.technology时Nginx返回400 Bad Request错误,但直接访问对应IP192.81.211.160站点可正常加载。Webconfs头部检测显示域名请求返回400响应头,IP请求返回200响应头。站点DNS和托管在Digital Ocean,基于Django开发,已设置Debug=False并配置ALLOWED_HOSTS。
域名访问响应头(400)
HTTP/1.1 400 Bad Request => Server => nginx/1.14.0 (Ubuntu) Date => Sun, 23 Apr 2023 20:24:50 GMT Content-Type => text/html Connection => close X-Content-Type-Options => nosniff Referrer-Policy => same-origin
IP访问响应头(200)
HTTP/1.1 200 OK => Server => nginx/1.14.0 (Ubuntu) Date => Sun, 23 Apr 2023 20:23:35 GMT Content-Type => text/html; charset=utf-8 Content-Length => 6857 Connection => close X-Frame-Options => DENY Vary => Cookie X-Content-Type-Options => nosniff Referrer-Policy => same-origin
Nginx调试日志片段
2023/04/23 20:42:39 [debug] 13352#13352: *2 http upstream dummy handler 2023/04/23 20:42:39 [debug] 13352#13352: *2 http upstream request: "/?" 2023/04/23 20:42:39 [debug] 13352#13352: *2 http upstream dummy handler 2023/04/23 20:42:39 [debug] 13352#13352: *2 http upstream request: "/?" 2023/04/23 20:42:39 [debug] 13352#13352: *2 http upstream process header 2023/04/23 20:42:39 [debug] 13352#13352: *2 malloc: 000056424E53BD20:4096 2023/04/23 20:42:39 [debug] 13352#13352: *2 recv: eof:0, avail:1 2023/04/23 20:42:39 [debug] 13352#13352: *2 recv: fd:12 190 of 4096 2023/04/23 20:42:39 [debug] 13352#13352: *2 http proxy status 400 "400 Bad Request" 2023/04/23 20:42:39 [debug] 13352#13352: *2 http proxy header: "Server: gunicorn" 2023/04/23 20:42:39 [debug] 13352#13352: *2 http proxy header: "Date: Sun, 23 Apr 2023 20:42:39 GMT" 2023/04/23 20:42:39 [debug] 13352#13352: *2 http proxy header: "Connection: close" 2023/04/23 20:42:39 [debug] 13352#13352: *2 http proxy header: "Content-Type: text/html" 2023/04/23 20:42:39 [debug] 13352#13352: *2 http proxy header: "X-Content-Type-Options: nosniff" 2023/04/23 20:42:39 [debug] 13352#13352: *2 http proxy header: "Referrer-Policy: same-origin" 2023/04/23 20:42:39 [debug] 13352#13352: *2 http proxy header done 2023/04/23 20:42:39 [debug] 13352#13352: *2 xslt filter header 2023/04/23 20:42:39 [debug] 13352#13352: *2 HTTP/1.1 400 Bad Request Server: nginx/1.14.0 (Ubuntu) Date: Sun, 23 Apr 2023 20:42:39 GMT Content-Type: text/html Transfer-Encoding: chunked Connection: keep-alive X-Content-Type-Options: nosniff Referrer-Policy: same-origin 2023/04/23 20:42:39 [debug] 13352#13352: *2 write new buf t:1 f:0 000056424E567A58, pos 000056424E567A58, size: 236 file: 0, size: 0 2023/04/23 20:42:39 [debug] 13352#13352: *2 http write filter: l:0 f:0 s:236 2023/04/23 20:42:39 [debug] 13352#13352: *2 http cacheable: 0 2023/04/23 20:42:39 [debug] 13352#13352: *2 posix_memalign: 000056424E53CD30:4096 @16 2023/04/23 20:42:39 [debug] 13352#13352: *2 http proxy filter init s:400 h:0 c:0 l:-1 2023/04/23 20:42:39 [debug] 13352#13352: *2 http upstream process upstream 2023/04/23 20:42:39 [debug] 13352#13352: *2 pipe read upstream: 0 2023/04/23 20:42:39 [debug] 13352#13352: *2 pipe preread: 0
问题原因分析
从Nginx调试日志可见,400错误实际是上游gunicorn服务返回的,而非Nginx直接拒绝请求。结合域名访问报错、IP访问正常的现象,核心原因集中在以下几点:
Nginx未正确传递Host头到gunicorn
访问IP时请求的Host头是IP地址,访问域名时Host头是exhibit.technology。如果Nginx配置中缺少proxy_set_header Host $host;,gunicorn转发给Django的请求会缺失正确的Host信息,触发Django的ALLOWED_HOSTS校验失败,返回400错误。Django的ALLOWED_HOSTS配置不完整
即便已配置ALLOWED_HOSTS,可能存在拼写错误,或未包含exhibit.technology(比如仅添加了IP或子域名),导致域名请求被Django拦截。DNS解析异常导致Host头格式错误
极少数情况下,DNS解析异常会导致请求的Host头包含多余字符,触发Nginx或Django的请求校验逻辑。
解决方案
- 修复Nginx配置:在对应server块的proxy配置中添加Host头传递规则,示例:
location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
修改后重启Nginx:sudo systemctl restart nginx
- 验证Django的ALLOWED_HOSTS:确保settings.py中包含目标域名,示例:
ALLOWED_HOSTS = ['192.81.211.160', 'exhibit.technology']
修改后重启gunicorn服务。
- 排查DNS解析:本地执行
nslookup exhibit.technology确认解析结果为目标IP,再用curl -v http://exhibit.technology观察请求的Host头是否正确。
内容的提问来源于stack exchange,提问作者Andrew

