fix(tunnel): 协议不写死 HTTP/2,按 auto→http2 候选回退(修「启动超时(30s)」) - #133
Open
Xiao-Jiang-233 wants to merge 1 commit into
Open
Xiao-Jiang-233 wants to merge 1 commit into
Xiao-Jiang-233 wants to merge 1 commit into
Conversation
现象:命名/快速隧道开启后一直卡在「启动中」,30 秒后报 「cloudflared 启动超时(30s)——请检查 Tunnel Token / 域名 Service / 关代理」, 但 Token、ingress Service 都是对的,关掉代理也没用。 根因:插件无条件 --protocol http2(为躲开国内被屏蔽的 UDP 7844)。 但反过来的网络也存在:代理 TUN(Clash 等)或企业网关会掐掉到 Cloudflare 边缘的 TCP,却不拦 UDP/QUIC。这时 cloudflared 自己的预检其实是: UDP Connectivity region1/2.v2.argotunnel.com PASS QUIC connection successful TCP Connectivity region1/2.v2.argotunnel.com FAIL HTTP/2 connection is blocked or unreachable suggested_protocol=quic 可因为写死了 http2,进程只会一次次 "TLS handshake with edge error: EOF" 重试,永远 等不到 Registered tunnel connection,最后只剩一句指不到真因的超时提示。 同一台机器改用 --protocol auto(或 quic)注册耗时不到 1 秒。 改动: - 新增 PROTOCOL_CANDIDATES = ['auto', 'http2'] 与 spawnCloudflaredWithFallback(): 逐个协议拉起 cloudflared,单个协议 timeoutMs(默认 20s)内没注册成功就杀掉换下一个; 进程自己退出(参数错误、Token 无效等)立刻换下一个,真错误不被超时掩盖; 全部失败时抛最后一条原因,并带上 cloudflared 输出的关键行(firstMeaningfulErrorLine)。 - 命名隧道与快速隧道都改走该 helper,不再写死 --protocol。 - 失败路径 kill 掉上一次尝试的子进程,避免留下孤儿 cloudflared。 - 两个入口支持 internals.spawn 注入,协议回退逻辑可在任意平台做单测 (新增 test/tunnel-protocol-fallback.test.js:候选顺序、失败信息保留真因)。 验证: - 真实环境(Clash TUN:到边缘的 TCP 被拦、QUIC 通,cloudflared 2026.9.1): 改前 30s 超时;改后 --protocol auto 注册成功,约 1s。 - npm test:新增 2 条用例通过;本机 Windows 下失败的 6 条(download/proxy/smoke/ tunnel-args 里 spawn 无扩展名假二进制)与本次改动无关,改动前同样失败。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
命名隧道(可能也包括快速隧道)开启后一直卡在「启动中」,30 秒后报:
但 Token、ingress Service 都是对的,退出代理也没用——因为真正被挡住的不是「隧道」,而是「HTTP/2」。
根因
插件为了躲开国内常被屏蔽的 UDP 7844,无条件写死
--protocol http2(lib/tunnel.mjs 两处)。可是反过来的网络同样存在:代理 TUN(Clash 等)或企业网关会掐掉到 Cloudflare 边缘的 TCP,却不拦 UDP/QUIC。这种机器上 cloudflared 自己的连通性预检是「QUIC 通、HTTP/2 不通」:
但只要
--protocol http2写死,cloudflared 就只会一次次TLS handshake with edge error: EOF重试,永远等不到Registered tunnel connection,于是插件只能给出那句指不到真因的超时提示(该机器上 Token 完全有效、公网域名 ingress 也正确——把协议改成 auto/quic 后注册耗时不到 1 秒)。改动
PROTOCOL_CANDIDATES = ['auto', 'http2']与spawnCloudflaredWithFallback():timeoutMs(默认 20s)内没注册成功就杀掉换下一个;firstMeaningfulErrorLine),不再只给一句「超时」。--protocol;internals.spawn注入,协议回退逻辑可在任意平台做单测(与仓库里internals.createProxy等既有约定一致)。为什么是
auto打头而不是quic:auto先跑预检,UDP 7844 被丢包的国内网络会自动落到 HTTP/2;预检判不出可用协议时进程只会无限重试,所以再显式http2兜底一次。两种被拦方向都能自愈,最坏情况从「永远起不来」变成「多等一个 20s 窗口」。验证
--protocol auto注册成功,约 1s。test/tunnel-protocol-fallback.test.js:候选顺序(前一个协议失败→换下一个→成功)、全失败时错误信息保留 cloudflared 的真因。npm test通过。git stash回到改动前同样失败,CI(Linux)不受影响。兼容性
对外行为不变:仍是「就绪判据 = 出现 Registered tunnel connection」,设置页、状态机、快速隧道 URL 解析都没动;只是把「一个写死的协议」换成「按候选顺序试」。