Cloudflare Tunnel 网络问题排查指南

问题现象

日志中出现以下错误:

ERR failed to dial to edge with quic: timeout: no recent network activity
ERR TLS handshake with edge error: EOF
ERR there are no free edge addresses left to resolve to
ERR Connection terminated error="there are no free edge addresses left to resolve to"

原因分析

这是典型的国内网络访问 Cloudflare 边缘节点困难的问题:

  1. QUIC 协议被限制:Cloudflare 默认使用 QUIC(HTTP/3),但在某些网络环境下连接不稳定
  2. TLS 握手失败:网络延迟或防火墙导致 TLS 握手超时
  3. 边缘节点不可达:Cloudflare 的边缘节点 IP 可能被限制访问

解决方案(按优先级)

方案 1:使用 HTTP/2 协议(已配置,推荐)

已自动配置:所有 docker-compose 文件已添加 --protocol http2 参数。

HTTP/2 比 QUIC 更稳定,在国内网络环境下连接成功率更高。

验证:

# 重启容器以应用新配置
docker restart mbe-tunnel-dev
docker restart mbe-cloudflared

# 查看日志,应该看到使用 http2 协议
docker logs mbe-tunnel-dev --tail 20

方案 2:检查并优化 Docker 网络配置

确保容器能正确访问后端服务:

# 检查开发版网络
docker network inspect mbe-dev-network

# 检查生产版网络
docker network inspect mbe-monorepo_default

# 测试容器间通信
docker exec mbe-tunnel-dev ping -c 2 mbe-api-dev
docker exec mbe-cloudflared ping -c 2 mbe-api

方案 3:配置代理(如果需要)

如果您的网络环境需要代理访问外网:

3.1 在 docker-compose 中配置代理

编辑 docker-compose.dev.cloudflare.ymldocker-compose.cloudflare.yml

environment:
  - TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN_DEV}
  - HTTP_PROXY=http://proxy.example.com:8080
  - HTTPS_PROXY=http://proxy.example.com:8080
  - NO_PROXY=localhost,127.0.0.1,mbe-api-dev

3.2 配置 Docker 代理

创建或编辑 ~/.docker/config.json

{
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.example.com:8080",
      "httpsProxy": "http://proxy.example.com:8080",
      "noProxy": "localhost,127.0.0.1"
    }
  }
}

方案 4:使用 Cloudflare WARP 客户端(最佳方案)

Cloudflare WARP 是 Cloudflare 提供的 VPN 服务,可以优化访问 Cloudflare 网络。

4.1 安装 WARP

Windows:

  1. 下载:https://1.1.1.1/
  2. 安装并启动 WARP
  3. 启用连接

macOS:

brew install cloudflare-warp
warp-cli register
warp-cli connect

Linux:

# Ubuntu/Debian
curl https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list
sudo apt update
sudo apt install cloudflare-warp
sudo warp-cli register
sudo warp-cli connect

4.2 Docker 使用 WARP 网络

如果 WARP 在宿主机运行,Docker 容器会自动使用 WARP 网络。

验证:

# 重启容器
docker restart mbe-tunnel-dev
docker restart mbe-cloudflared

# 查看日志,应该看到连接成功
docker logs mbe-tunnel-dev --tail 20

方案 5:增加重试和超时配置

创建配置文件 deploy/cloudflared/config-dev.yml

tunnel: <TUNNEL_ID>
credentials-file: /root/.cloudflared/<TUNNEL_ID>.json

# 使用 HTTP/2 协议
protocol: http2

# 重试配置
retries: 10
grace-period: 30s

# 连接超时配置
originRequest:
  connectTimeout: 30s
  tcpKeepAlive: 15s
  keepAliveConnections: 100
  keepAliveTimeout: 90s
  noHappyEyeballs: false

ingress:
  - hostname: dev.hi-maker.com
    service: http://mbe-api-dev:8000
  - service: http_status:404

然后在 docker-compose 中使用:

volumes:
  - ./deploy/cloudflared/config-dev.yml:/etc/cloudflared/config.yml:ro
command: tunnel --config /etc/cloudflared/config.yml run

方案 6:使用 Cloudflare 的 Argo Tunnel(高级)

如果以上方案都无效,可以考虑使用 Cloudflare 的 Argo Tunnel 服务,它提供更好的网络连接。

验证修复

1. 检查 Tunnel 日志

# 开发版
docker logs mbe-tunnel-dev --tail 50

# 生产版
docker logs mbe-cloudflared --tail 50

成功标志:

INF Registered tunnel connection connIndex=0 connection=xxx event=0 ip=xxx location=xxx protocol=http2

失败标志:

ERR failed to dial to edge
ERR TLS handshake with edge error

2. 检查 Cloudflare Dashboard

  1. 访问:https://one.dash.cloudflare.com/
  2. 进入:Networks > Tunnels
  3. 查看 Tunnel 状态应为 HEALTHY

3. 测试访问

# 测试开发版
curl https://dev.hi-maker.com/api/health

# 测试生产版
curl https://mbe.hi-maker.com/api/health

常见问题

Q1: 重启后仍然连接失败

解决:

  1. 检查环境变量是否正确加载
  2. 检查 Token 是否有效
  3. 尝试使用 WARP 客户端

Q2: 开发版正常,生产版失败

检查:

  1. 生产版 Token 是否正确
  2. 生产版 API 服务是否运行
  3. Cloudflare Dashboard 中的 Service URL 是否正确

Q3: 间歇性连接失败

原因: 网络不稳定

解决:

  1. 使用 WARP 客户端
  2. 增加重试次数
  3. 使用配置文件方式,设置更长的超时时间

推荐配置顺序

  1. 使用 HTTP/2 协议(已配置)
  2. 检查 Docker 网络配置
  3. 🔄 如果仍然失败,安装 WARP 客户端
  4. 🔄 如果 WARP 不可用,配置代理
  5. 🔄 最后考虑使用配置文件方式

监控建议

定期检查 Tunnel 状态:

# 每天检查一次
docker logs mbe-tunnel-dev --tail 100 | Select-String "ERR"
docker logs mbe-cloudflared --tail 100 | Select-String "ERR"

如果发现大量错误,及时应用上述解决方案。