Cloudflare Tunnel + Nginx 反向代理导致重定向循环的排查与修复
Cloudflare Tunnel + Nginx 反向代理导致重定向循环的排查与修复
背景
最近在维护一个 WordPress 多站点时遇到一个典型的"重定向次数过多"问题。架构是这样的:
- 主站点
aiwp.pro通过 Cloudflare Tunnel 连接到服务器 - 需要将
aiwp.pro的流量反向代理到同一台服务器上的另一个站点chimy.cn/aiwp/ chimy.cn是一个 WordPress 子目录型多站点(Multisite)
访问 https://chimy.cn/aiwp/ 时,浏览器直接报错:重定向次数过多。
架构速览
整个请求链路如下:
用户 → https://aiwp.pro/
→ Cloudflare 边缘节点(HTTPS 终止)
→ Cloudflare Tunnel(HTTP → localhost:80)
→ Nginx(aiwp.pro 站点配置)
→ proxy_pass → https://chimy.cn/aiwp/
→ Cloudflare(chimy.cn)
→ Nginx(chimy.cn 站点配置)
→ WordPress 多站点
问题排查
第 1 步:检查 Nginx 配置
查看 aiwp.pro 的 Nginx 配置文件 aiwp.pro.conf:
#HTTP_TO_HTTPS_START
set $isRedcert 1;
if ($server_port != 443) {
set $isRedcert 2;
}
if ( $uri ~ /.well-known/ ) {
set $isRedcert 1;
}
if ($isRedcert != 1) {
rewrite ^(/.*)$ https://$host$1 permanent;
}
#HTTP_TO_HTTPS_END
这是常见的 HTTP 强制跳转 HTTPS 规则。当 Nginx 在端口 80 收到 HTTP 请求时,返回 301 重定向到 HTTPS 地址。
#PROXY-CONF-START
location ^~ / {
proxy_pass https://chimy.cn/aiwp/;
proxy_set_header Host chimy.cn;
...
}
#PROXY-CONF-END
反向代理将请求转发到 https://chimy.cn/aiwp/。
第 2 步:分析重定向循环
关键问题出在 Cloudflare Tunnel + HTTP 强制跳转 的配合上。
Cloudflare Tunnel 的工作原理:Cloudflare 边缘节点通过 Tunnel 连接到服务器时,始终使用 HTTP(端口 80) 建立连接,即使客户端浏览器使用的是 HTTPS。
于是循环就产生了:
1. 浏览器 → https://aiwp.pro/
2. Cloudflare 边缘节点 → Tunnel → HTTP localhost:80
3. Nginx 收到 HTTP 请求
4. HTTP→HTTPS 跳转规则触发
5. 返回 301 → Location: https://aiwp.pro/
6. Cloudflare 收到 301 重定向
7. 通过 Tunnel 再次以 HTTP 连接 localhost:80
8. Nginx 再次收到 HTTP 请求
9. goto 步骤 4 → 死循环!
浏览器提示"重定向次数过多",正是因为这个循环在持续。
第 3 步:检查 WordPress 配置
继续检查 chimy.cn 的 WordPress 配置,看看是否有其他问题。
wp-config.php 中的关键配置:
define('WP_ALLOW_MULTISITE', true);
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', false); // 子目录型多站点
define('DOMAIN_CURRENT_SITE', $_SERVER['HTTP_HOST']);
define('PATH_CURRENT_SITE', '/');
define('WP_SITEURL', $protocol . '://' . $_SERVER['HTTP_HOST']);
define('WP_HOME', WP_SITEURL);
站点 URL 是动态根据 HTTP_HOST 请求头设置的。这意味着当反向代理传入 Host: chimy.cn 时,WordPress 会正确地将自身识别为 https://chimy.cn。
数据库查询确认 wp_blogs 表中只有主站点(chimy.cn,路径 /),没有 /aiwp/ 子站点记录。这意味着 WordPress 会以主站点来处理 /aiwp/ 路径的请求,而不会触发重定向——所以问题不在 WordPress 这边。
第 4 步:发现问题根源
综合以上分析,根本原因是 Cloudflare Tunnel 的 HTTP 连接与 Nginx 的强制 HTTPS 跳转产生了冲突。
另外还发现一个次要问题:proxy_pass https://chimy.cn/aiwp/ 中的 chimy.cn 域名通过 DNS 解析到了 Cloudflare 的 IP,导致代理请求从本机 Nginx 出去后,又经过 Cloudflare 绕回本机,多了一层不必要的网络中转。
解决方案
修复 1:移除 HTTP→HTTPS 强制跳转
由于 Cloudflare 已经在边缘节点处理了 HTTPS 终止,Nginx 不再需要做 HTTP→HTTPS 跳转。直接移除相关规则:
# 修改前
#HTTP_TO_HTTPS_START
set $isRedcert 1;
if ($server_port != 443) {
set $isRedcert 2;
}
if ( $uri ~ /.well-known/ ) {
set $isRedcert 1;
}
if ($isRedcert != 1) {
rewrite ^(/.*)$ https://$host$1 permanent;
}
#HTTP_TO_HTTPS_END
# 修改后
#HTTP_TO_HTTPS_START
# Cloudflare 已处理 HTTPS 终止,无需在此强制跳转
#HTTP_TO_HTTPS_END
修复 2:proxy_pass 直连本地
将代理目标从公共域名改为本地回环地址,绕开 Cloudflare:
# 修改前
proxy_pass https://chimy.cn/aiwp/;
# 修改后
proxy_pass https://127.0.0.1/aiwp/;
proxy_ssl_verify off;
这样代理请求直接走本地回环(loopback),不再经过 Cloudflare,既减少了网络延迟,也避免了潜在的重定向问题。
修复后的配置
location ^~ / {
proxy_pass https://127.0.0.1/aiwp/;
proxy_set_header Host chimy.cn;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_ssl_verify off;
proxy_ssl_server_name on;
...
}
最终流量路径
用户 → https://aiwp.pro/
→ Cloudflare 边缘节点(HTTPS 终止)
→ Cloudflare Tunnel(HTTP → localhost:80)
→ Nginx aiwp.pro(无 HTTP→HTTPS 跳转)
→ proxy_pass 直连 127.0.0.1:443
→ Nginx chimy.cn
→ WordPress 多站点
教训与总结
1. Cloudflare Tunnel 的协议理解
Cloudflare Tunnel 始终以 HTTP 连接本地服务,不论客户端使用什么协议。这意味着本地 Nginx 不需要也不能再做协议跳转,否则就会和 Cloudflare 形成循环。
2. 反向代理避免回环
当代理目标域名解析到 Cloudflare IP 时,请求会多一层网络中转。对于同机代理的场景,直接使用 127.0.0.1 本地回环地址是最优选择。
3. 排查思路
面对"重定向次数过多"这类问题,可以按以下步骤排查:
- 第一步:用
curl -I测试每个环节的 HTTP 响应头和重定向链 - 第二步:理清完整的请求链路,检查每一层是否有跳转规则
- 第三步:关注反向代理和 CDN/Tunnel 的协议交互(HTTP vs HTTPS)
- 第四步:检查后端应用的 URL 配置是否与代理后的请求 URL 一致
写在最后
Cloudflare Tunnel 是一个很方便的内网穿透工具,但在配合 Nginx 反向代理使用时,需要特别注意 HTTP/HTTPS 协议的处理。Cloudflare 处理了 HTTPS,你的 Nginx 就不要再做 HTTPS 强制跳转了——这听起来简单,但在实际配置中很容易被忽略。
只要理解了这一点,类似的"重定向循环"问题就能迎刃而解了。