根本原因是nginx反向代理未透传x-forwarded-proto等关键头,导致后端误判协议并301跳转,叠加proxy_redirect误改location形成循环;需设proxy_set_header x-forwarded-proto $scheme;及proxy_redirect off;

为什么 Nginx 反向代理会导致“重定向次数过多”
根本原因不是宝塔面板本身,而是反向代理配置中 proxy_set_header Host 和 proxy_redirect 的组合触发了循环跳转。典型场景是:后端服务(比如 Node.js 或 Django)收到请求后,发现 Host 头不对或缺少 X-Forwarded-Proto,就主动 301 跳转到它认为“正确”的地址——而这个地址又再次打回 Nginx,形成闭环。
检查 proxy_set_header 是否漏掉关键头
宝塔默认的反向代理模板常只写 proxy_set_header Host $host;,但多数现代应用依赖 X-Forwarded-Proto 和 X-Real-IP 来判断协议和来源。漏掉它们,后端可能误判为 HTTP 请求,强制跳 HTTPS;或因无法识别真实客户端 IP,触发安全重定向。
-
proxy_set_header Host $host;→ 改成proxy_set_header Host $http_host;(保留端口和原始 Host) - 必须补上:
proxy_set_header X-Forwarded-Proto $scheme; - 建议加上:
proxy_set_header X-Real-IP $remote_addr;和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect 没关干净,后端返回的 Location 被二次改写
当后端返回 Location: http://example.com/xxx,Nginx 默认会用 proxy_redirect 把它替换成当前 server 块的域名。如果配置不当(比如用了 proxy_redirect on; 或匹配规则太宽),就可能把本该保留的跳转地址又塞回自己,造成循环。
- 最稳妥做法:显式关闭自动重写,加一行
proxy_redirect off; - 如果后端返回的是绝对路径且域名固定,可精确控制:
proxy_redirect http://backend/ /; - 避免使用
proxy_redirect default;—— 它在多层代理或 HTTPS 场景下极易出错
确认后端是否在代码里硬编码跳转逻辑
有些框架(如 Laravel、Flask、Express)会在中间件里检查 req.headers['x-forwarded-proto'] 或 request.scheme,一旦为空或不是 https,就强制 301。这时即使 Nginx 配对了,只要 header 没透传过去,照样跳。
- 临时验证:curl -H "X-Forwarded-Proto: https" http://你的域名,看是否还跳
- Django 用户检查
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')是否启用 - Node.js 用户确认是否调用了类似
res.redirect('https://' + req.get('host') + req.url)这类硬跳逻辑
真正卡住的地方往往不在 Nginx 配置本身,而在后端对转发头的信任链断了一环——少一个 X-Forwarded-Proto,整个跳转逻辑就失准。











