网站接入 CDN 后陷入 301/302 重定向循环?Host、HTTPS 回源与代理头排查指南
本内容发表于:2026-09-17 16:28:53
浏览量
1030

CDN 301/302 重定向循环排查示意图

网站直连源站正常,接入 CDN 后却不断跳转,浏览器最后报 ERR_TOO_MANY_REDIRECTS。这类故障通常不是某一条 301 或 302 本身有问题,而是 CDN、负载均衡、Nginx 与应用对“当前协议和当前域名”的判断不一致:上一层认为请求已经是 HTTPS,下一层仍把它当成 HTTP;或者 CDN 回源时改了 Host,源站又把请求跳回另一个域名。

排查时不要先清浏览器缓存,也不要一次性关闭全部 HTTPS 规则。先把完整跳转链打印出来,确认是哪两个地址或哪两层组件在互相改写,再动配置。

先确认是否真的是重定向循环

用 curl 查看响应头,不自动跟随跳转:

curl -I https://www.example.com/

重点看状态码和 Location。再用下面的命令跟随跳转并输出结果:

curl -sS -L -o /dev/null \
  -w 'final=%{url_effective} code=%{http_code} redirects=%{num_redirects}\n' \
  --max-redirs 15 https://www.example.com/

若要看完整过程:

curl -v -L --max-redirs 10 https://www.example.com/ -o /dev/null

常见循环有三种:

  • http://example.com 与 https://example.com 来回跳;

  • example.com 与 www.example.com 来回跳;

  • 外部地址不变,但 CDN 和源站反复返回同一个 Location。

浏览器只会告诉你“跳转太多”,curl 的跳转链才能说明是谁先跳、跳到了哪里。

对比 CDN 地址和源站直连结果

先请求 CDN 正常域名,再绕过 DNS 直接访问源站。假设源站 IP 是 203.0.113.10:

curl -I https://www.example.com/
curl -I --resolve www.example.com:443:203.0.113.10 https://www.example.com/

--resolve 会把连接发到指定 IP,同时保留 URL 中的域名和 TLS SNI,比直接访问 https://203.0.113.10/ 更接近真实请求。

源站直连返回 200,经过 CDN 才循环,优先检查 CDN 的回源协议、回源 Host 和边缘跳转规则;两边都循环,则故障多半在 Nginx、应用或负载均衡配置。

检查 CDN 到源站到底使用 HTTP 还是 HTTPS

访问者到 CDN 是 HTTPS,不代表 CDN 到源站也是 HTTPS。CDN 常见的回源策略包括仅 HTTP、仅 HTTPS、跟随访问者协议。若边缘用 HTTPS 接收请求,却用 HTTP 回源,而源站又把所有 HTTP 请求重定向到 HTTPS,就可能形成闭环。

以 CloudFront 为例,自定义源站可配置 HTTP Only、HTTPS Only 或 Match Viewer。其他 CDN 的名称可能不同,但判断逻辑一样。源站已经正确部署证书时,通常应让 CDN 以 HTTPS 回源,并确认源站证书覆盖实际回源主机名。

修改前先记录当前策略,再做小范围验证。不要在 CDN、Nginx、应用和 WordPress 插件里同时新增“强制 HTTPS”,否则出问题时很难确定是哪一层返回的跳转。

核对 Host 请求头和站点规范域名

同一个源站经常托管多个虚拟主机。CDN 回源时如果把 Host 改成源站域名,Nginx 可能落到默认 server,应用也可能根据错误的主机名生成跳转。

先模拟两种 Host:

curl -I http://203.0.113.10/ -H 'Host: www.example.com'
curl -I http://203.0.113.10/ -H 'Host: origin.example.net'

如果两次返回的 Location 不同,就要统一这三个位置:CDN 的回源 Host、Nginx 的 server_name、应用设置中的站点 URL。目标是让系统只保留一个规范域名,例如全部收敛到 https://www.example.com,而不是边缘要求带 www、源站又要求去掉 www。

使用 CloudFront 时还要注意:默认情况下,它可把 Host 设置为关联的源站域名;是否转发访问者 Host 取决于请求策略。调整 Host 会影响虚拟主机匹配、TLS 证书校验和缓存设计,不能只改一处后直接全量上线。

让应用正确识别访问者最初使用的协议

反向代理后的应用看到的连接,可能只是代理到源站的 HTTP 连接。若应用不知道访问者最初使用的是 HTTPS,它会不断把请求重定向到 HTTPS,即使浏览器地址栏已经是 HTTPS。

X-Forwarded-Proto 常用于记录访问者连接到代理或负载均衡时使用的协议。例如:

X-Forwarded-Proto: https

但这个头不能无条件信任。源站应只接受来自可信 CDN、负载均衡或反向代理的协议头,并覆盖外部客户端自行提交的同名请求头。不同 CDN 使用的头名称也可能不同;CloudFront 可使用 CloudFront-Forwarded-Proto 参与请求策略,而不是简单保留访问者传入的 X-Forwarded-Proto。

Nginx 继续代理到应用时,常见写法是:

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

这里的 $scheme 代表 Nginx 当前接收到的协议。如果 Nginx 前面还有一层 CDN 或负载均衡,不能想当然地认为它等于访问者协议;需要先由可信上游传入并由应用按框架要求配置“可信代理”。

排除重复和冲突的跳转规则

把所有可能产生跳转的位置列出来:

  • CDN 的 HTTP 转 HTTPS、URL Redirect、边缘函数;

  • 负载均衡监听器规则;

  • Nginx 或 Apache 的 rewrite、return;

  • 应用框架的 HTTPS 中间件;

  • WordPress 的站点地址与重定向插件;

  • HSTS 和浏览器缓存的永久重定向。

最稳妥的做法是选定一层负责“规范跳转”。例如让 CDN 负责 HTTP 到 HTTPS,让源站只处理业务路径;或者让 CDN 保留协议信息,由应用统一生成规范 URL。不要让两层用相反的规则处理同一件事。

临时测试 301 时要谨慎。301 和 308 容易被浏览器或中间缓存长期记住,排查阶段可先用 302 或 307,确认规则正确后再改为永久跳转。

检查 CDN 是否缓存了错误的 301/302

配置已经修正,访问仍然循环,可能是边缘节点还保留着旧的重定向响应。检查响应中的 Age、Via、CDN 命中标记和 Location,再对受影响路径执行缓存失效。

不要一上来清空整个站点缓存。先失效首页或具体路径,验证新响应后再扩大范围。对登录、地区判断、设备判断等动态跳转,通常不应按一个过于简单的缓存键长期缓存;相关 Cookie、查询参数或请求头是否参与规则,需要与实际业务一致。

一套可回滚的修复顺序

  1. 保存 CDN、负载均衡、Nginx 和应用当前配置。

  2. 用 curl 记录修改前的完整跳转链。

  3. 统一规范域名,消除 www 与裸域名的双向跳转。

  4. 统一 CDN 回源协议;源站支持有效证书时优先 HTTPS 回源。

  5. 核对回源 Host、SNI 与源站虚拟主机是否匹配。

  6. 配置可信代理,让应用识别最初的 HTTPS 请求。

  7. 暂时只保留一层 HTTPS 强制跳转。

  8. 小范围失效相关 301/302 缓存,再从不同网络复测。

每次只改一个变量。一次改完五层配置,即使网站恢复,也很难知道哪一项才是原因。

修复后如何验证

curl -I http://www.example.com/
curl -I https://www.example.com/
curl -sS -L -o /dev/null \
  -w 'final=%{url_effective} code=%{http_code} redirects=%{num_redirects}\n' \
  --max-redirs 10 http://www.example.com/

理想结果通常是:HTTP 只跳一次到规范 HTTPS 地址,HTTPS 页面直接返回 200;页面内链、登录回调、API 与静态资源不再切换协议或域名。再检查源站日志,确认请求进入了正确的虚拟主机,Host 和可信代理协议字段符合预期。

如果循环只在个别地区出现,还要比较不同边缘节点的缓存状态和配置发布时间。CDN 配置传播和旧重定向缓存可能让问题看起来时好时坏。

参考资料

  • Amazon CloudFront Developer Guide:Request and response behavior for custom origins,核查日期:2026 年 9 月 17 日

  • Amazon CloudFront Developer Guide:Require HTTPS for communication between CloudFront and your custom origin,核查日期:2026 年 9 月 17 日

  • Amazon CloudFront Developer Guide:Control origin requests with a policy,核查日期:2026 年 9 月 17 日

  • NGINX Documentation:ngx_http_proxy_module,核查日期:2026 年 9 月 17 日

  • Cloudflare SSL/TLS Documentation:ERR_TOO_MANY_REDIRECTS,核查日期:2026 年 9 月 17 日

  • MDN Web Docs:X-Forwarded-Proto header,核查日期:2026 年 9 月 17 日