当前位置:首页 >  IDC >  服务器 >  正文

重定向循环与 HTTPS 识别错乱:X-Forwarded-Proto 那些坑

 2026-09-06 11:03  来源: 互联网   我来投稿 撤稿纠错

  一键部署OpenClaw

HTTPS 证书配好、Nginx 强制跳转也配好了,浏览器打开却提示 ERR_TOO_MANY_REDIRECTS,重定向次数超限。这个故障的高发场景非常固定:网站前面挂了 CDN、负载均衡或者第二层反向代理。浏览器到 CDN 是 HTTPS,但 CDN 回源到你的 Nginx 走的是 HTTP,于是循环就来了。

拆开看这个循环:你的 Nginx 配了“http 访问就 301 到 https”,可它收到的永远是 http 回源请求,于是每次都 301 跳 https,CDN 又用 http 回源,再收到 301,无限套娃。后端应用也一样倒霉——PHP 里 $_SERVER['HTTPS'] 永远是空的,凡是根据它判断协议的逻辑全部失灵,生成的资源链接全是 http://,又被浏览器的混合内容策略拦一道。

# 断案第一步:看响应头,确认到底在循环什么
curl -sI http://你的域名/ | grep -iE "HTTP/|location"

# 断案第二步:看 Nginx 访问日志里 $scheme 字段,回源请求是不是全是 http
tail -f /var/log/nginx/access.log | awk '{print $6, $9}' | sort | uniq -c

问题本质是协议信息在代理层丢了。标准解法是让代理层把真实协议通过 X-Forwarded-Proto 头传给后端,后端以这个头为准做判断。MDN 对这个头的定义就是:代理服务器用它告诉后端,客户端发起的请求原本是 http 还是 https。

# 代理层(CDN 回源协议改 https,或本层反代):
server {
listen 80;
location / {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
}

# 源站 Nginx:只在“确认客户端真实协议是 http”时才跳转
server {
listen 8080;
set $forward_proto $http_x_forwarded_proto;
if ($forward_proto = "http") {
return 301 https://$host$request_uri;
}
# 正常服务……
}

# PHP 应用侧(以 WordPress 为例,wp-config.php 顶部):
# if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
# $_SERVER['HTTPS'] = 'on';

改完验证别只开浏览器看一眼,用 curl 把整条链路各请求一次:curl -I http:// 应该返回 301 且 Location 是 https;curl -I https:// 应该直接 200,不再出现 Location。如果 CDN 面板里有“回源协议”选项,直接改成 HTTPS 是更干净的做法,连判断逻辑都省了。还有一个容易忽略的点:HSTS 头。如果你配了 Strict-Transport-Security 又想临时回退到 http 调试,浏览器会强制走 https,测试时记得换无痕窗口,不然你看到的“循环”可能只是浏览器缓存了旧跳转。

这类故障的通用心法:凡是链路里出现了代理,所有依赖“客户端长什么样”的判断(协议、真实 IP、Host)都要改成看 X-Forwarded-* 头,并且要在每一层都正确传递。只修一层,问题换个姿势再回来。

相关阅读:重定向循环是接入层和代理层交叉的故障。《服务器故障排查总纲:按现象反查的五层定位法》里与本篇相邻的还有证书链、HTTPS 识别两篇,总纲一张表把关联故障串起来。

申请创业报道,分享创业好点子。点击此处,共同探讨创业新机遇!

相关标签
网站服务器

相关文章

  • PHP Allowed memory size exhausted:真泄漏还是配额太小

    日志里刷Fatalerror:Allowedmemorysizeof134217728bytesexhausted,后台某个导出功能一跑就挂。134217728字节就是128M,这是php.ini里memory_limit的官方默认值。很多人第一反应是把数字改大,先别急——内存溢出有两种完全不同的病

    标签:
    网站服务器
  • Nginx 403 Forbidden:权限、SELinux 与 deny 规则三层排查法

    新站刚部署,首页打开403Forbidden。403和404不一样,404是“没找到”,403是“找到了但不给你看”,所以问题一定出在服务端某一层权限上。Nginx报403的原因集中在三层:文件系统权限、SELinux、Nginx自身的访问控制规则,按这个顺序查,基本不会漏。先说最常见的文件系统权限

    标签:
    网站服务器
  • Nginx 413 Request Entity Too Large:三处上传限制一起改才算改完

    用户后台传一张3MB的图,页面转半天最后白屏,什么提示都没有。你去看浏览器请求,状态码413RequestEntityTooLarge。这个错误有个讨厌的特性:官方文档里明确写了浏览器没法正确渲染它,所以用户端看到往往不是413页面,而是一片白或者连接被重置,报障的时候只会说“传不上去”。根因就一句

    标签:
    网站服务器
  • SSL 证书过期与证书链不完整:openssl s_client 验证与续期监控

    证书过期这事,一旦发生就是全站级别的红色警告。浏览器直接拦截,访客看到的不是你的网站,是一屏吓人的安全提示。更气人的是它完全可以避免——免费证书加自动续期,配好了就再也不用管。Let'sEncrypt的证书有效期是90天,这个短期限是刻意设计的,目的是逼着大家把续期自动化。Certbot是它官方推荐

  • 进程被 OOM Kill:dmesg 定位与关键进程保护

    有一种故障特别难查:服务莫名其妙消失了,应用日志里什么都没留下,没有崩溃堆栈,没有异常退出记录。进程就这么凭空不见。碰到这种情况,十有八九是内核干的——内存不够了,OOMKiller挑中它杀了。OOM的全称是OutofMemory,它是内核的最后手段。Linux默认采用乐观的内存分配策略,进程申请内

热门排行

信息推荐