
网站直连源站正常,接入 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、查询参数或请求头是否参与规则,需要与实际业务一致。
一套可回滚的修复顺序
保存 CDN、负载均衡、Nginx 和应用当前配置。
用 curl 记录修改前的完整跳转链。
统一规范域名,消除
www与裸域名的双向跳转。统一 CDN 回源协议;源站支持有效证书时优先 HTTPS 回源。
核对回源 Host、SNI 与源站虚拟主机是否匹配。
配置可信代理,让应用识别最初的 HTTPS 请求。
暂时只保留一层 HTTPS 强制跳转。
小范围失效相关 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 日