首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Cloudflare Tunnel 调参实录:precheck 全 FAIL,隧道却是通的

Cloudflare Tunnel 调参实录:precheck 全 FAIL,隧道却是通的

原创
作者头像
用户10817318
发布于 2026-10-21 14:24:56
发布于 2026-10-21 14:24:56
240
举报

背景

家里那台电视盒子改造的小服务器已经跑了大半年,7 个容器,2G 内存。所有服务都在内网,出门就访问不到。

家宽没有公网 IPv4,这事没法绕:端口映射做不了,DDNS 也没意义。能选的方案就那么几个,最后用了 Cloudflare Tunnel——盒子主动往外连,不需要任何入站端口,也不需要在路由器上开洞。

装完之后能用了,但中间有一段折腾了很久,因为它的自检在骗人。

这篇文章只讲调参,不讲怎么装。如果你也在没有公网 IP 的环境下用 Tunnel,这几个坑大概率会踩到。

先给结论

赶时间的话看这张表,后面是推导过程。

配置

结果

默认(QUIC + 双栈)

唯一可用,注册 2 条连接

--protocol http2

隧道彻底连不上,一条都注册不了

--edge-ip-version 6

没有收益,反而 502

--edge-ip-version 4

掐掉唯一可用的通路

面板显示 Degraded

正常现象,不是故障

precheck 显示 FAIL

可能完全正常,别信

核心结论只有一句:不要动默认参数。

现象:自检报了一堆 FAIL

cloudflared 启动时会跑一段连通性预检,输出大概是这样:

代码语言:txt
复制
UDP Connectivity  region1.v2.argotunnel.com  FAIL  QUIC connection failed
TCP Connectivity  region1.v2.argotunnel.com  FAIL  HTTP/2 connection is blocked
SUMMARY: Environment has critical failures.

Environment has critical failures 这个措辞很吓人,看起来隧道彻底废了。

搜索这个报错,绝大多数答案都指向同一句话:

你的网络屏蔽了 UDP 7844,加 --protocol http2 走 TCP 就行。

听起来非常合理——UDP 被墙了就换 TCP,这是标准排查思路。于是我照着做了。

第一次误判:换成 HTTP/2

加完参数重启,结果是更彻底地连不上:

代码语言:txt
复制
ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity"
ERR Unable to establish connection with Cloudflare edge error="TLS handshake with edge error: EOF"
INF Retrying connection in up to 2s

无限重试,一条连接都注册不上。

这才回头去做正经的连通性测试。

实测:到底哪个端口是活的

三个候选路径,逐个测:

协议

端口

实测结果

QUIC(默认)

UDP 7844

可用,能注册连接

HTTP/2(--protocol http2)

TCP 7844

完全不可用,全部 i/o timeout

普通 HTTPS

TCP 443

正常

结论明确:这条宽带上 TCP 7844 是死的,UDP 7844 反而活着。

也就是说 precheck 报的「UDP FAIL」本身就不可靠,而它建议的替代方案(TCP 7844)才是真正不通的那条。

所以那句 Environment has critical failures 的正确理解是:它在几秒内测了两条路,两条都没测通过,但它不告诉你哪条实际上能用。

第二个坑:/dev/tcp 说通,握手还是超时

排查过程中我用过这个土办法:

代码语言:bash
复制
timeout 5 bash -c '</dev/tcp/198.41.200.13/7844' && echo "通" || echo "不通"

返回「通」。

但 cloudflared 那边依然是 TLS handshake ... i/o timeout。两边结论直接打架。

原因在于 /dev/tcp 只完成 TCP 三次握手——那都是小包。而 TLS 握手要收 ServerHello 和证书链,那是多个满包。中间链路如果对这种「握手成功后的大包」静默丢包,就会得到「连接建立成功,但数据全部丢失」的诡异状态。

所以 /dev/tcp 只能证明「对端回了 SYN-ACK」,不能证明「这条链路可用」。 用它判断端口通不通,在这个场景下是无效的。

这条经验对所有「握手能过、数据不通」的排查都适用。

--edge-ip-version 的两个方向都试过了

既然默认走 IPv6 边缘,那强制走 IPv4 行不行?

代码语言:txt
复制
--edge-ip-version 4   →  掐掉了唯一可用的 IPv6 通路,隧道断
--edge-ip-version 6   →  没有任何收益,反而开始出现 502

两个方向都是负收益。

连接数只有 2 条,面板 Degraded 不是故障

隧道连上之后,Cloudflare 面板显示 Degraded,连接数是 2。

一度以为是不稳定,反复重启。后来发现:

这条链路的连接数上限就是 2 条,而 Cloudflare 面板对少于 4 条连接的健康隧道会标记为 Degraded。

这是面板的判定阈值问题,不是你的隧道有问题。只要服务能访问,这个标记可以完全无视。

真正可信的判据

排查过程中我发现,日志里的判据也有坑。

数 Registered tunnel connection 出现的次数这个看起来很靠谱,实际会误报:

代码语言:bash
复制
# 这个结果不可靠
journalctl -u cloudflared | grep -c "Registered tunnel connection"

因为 journald 会滚动,日志被清掉之后这个数字会变成 0,看起来像从没连上过。

包括 systemctl is-active,它在某些时刻也会显示 activating 而不是 active,因为 cloudflared 是 Type=notify 服务,要等它自己上报就绪。

唯一可信的判据是从外部发一个真实请求:

代码语言:bash
复制
curl -sI https://你的域名 | head -1
# 期望:HTTP/2 200

这个判据的好处是它绕过了所有中间状态——不看进程在不在、不看日志怎么写,直接看「外部能不能访问到你的服务」。这才是用户真正关心的事。

正确的排查顺序

踩完之后整理了一套顺序,从「最可信」到「最不可信」:

代码语言:bash
复制
# ① 先看外部能不能访问(唯一有效判据)
curl -sI https://你的域名 | head -1

# ② 看有没有真正注册上连接
journalctl -u cloudflared -n 50 --no-pager | grep "Registered tunnel"

# ③ 恢复默认配置(把之前改坏的 override 删掉)
rm -f /etc/systemd/system/cloudflared.service.d/override.conf
systemctl daemon-reload
systemctl restart cloudflared --no-block
sleep 30

# ④ 再验一次
curl -sI https://你的域名 | head -1

这里有个细节值得单独说:systemctl restart 一定要加 --no-block。

cloudflared 是 Type=notify 服务,不加这个参数,systemctl restart 会阻塞在终端直到服务就绪或超时(最长 3 分钟)。看起来像命令卡死了,实际上是在等。加 --no-block 立刻返回。

我第一次遇到时以为 SSH 断了,还重连了一次。

收尾

几个可以直接拿去用的结论:

  • 别改协议。默认的 QUIC + 双栈就是最优解,--protocol http2 在多数家宽上是负优化
  • precheck 的 FAIL 不代表隧道坏了。它只测几秒,而且两条路都测,只要一条能用就够
  • /dev/tcp 测端口是假阳性。它只验证握手,不验证链路
  • 面板 Degraded 可能只是连接数没到阈值,不是故障
  • 健康判据要选外部的:curl -sI 比数日志可靠得多

折腾这一趟最大的收获不是某个参数,而是一个判断习惯:当工具的自检结论和实际现象矛盾时,先怀疑自检的判据,而不是现象。

precheck 测的是「能不能连上边缘节点」,我关心的是「别人能不能打开我的网站」。这两件事之间隔着好几层,precheck 失败完全不影响后者成立。


机器还在跑,欢迎交流。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 背景
  • 先给结论
  • 现象:自检报了一堆 FAIL
  • 第一次误判:换成 HTTP/2
  • 实测:到底哪个端口是活的
  • 第二个坑:/dev/tcp 说通,握手还是超时
  • --edge-ip-version 的两个方向都试过了
  • 连接数只有 2 条,面板 Degraded 不是故障
  • 真正可信的判据
  • 正确的排查顺序
  • 收尾
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档