使用 Cloudflare 实现内网穿透:配置过程和问题解决

date
Aug 22, 2024
slug
using-cloudflare-for-network-penetration-configuration-and-troubleshooting
status
Published
tags
工具
网络
summary
配置 Cloudflare Zero Trust Tunnel,解决 Docker 默认网络隔离导致容器无法访问宿主机服务的问题。
type
Post

配置过程

  1. 首先,登录到 Cloudflare 账号并进入 Dashboard。在左侧菜单栏中点击 “Zero Trust”,进入 Zero Trust 页面后,再点击 “Network - Tunnels”,进入 Tunnels 配置页面。
  1. 点击 “Create a Tunnel”,选择 “Cloudflared” 并点击 “Next”。为 Tunnel 命名后,继续点击 “Next”。
notion image
  1. 为了简化部署,这里使用 Docker。将页面中的命令复制到终端并执行。
notion image
如果配置成功,当前页面将显示已经成功连接的设备信息。
  1. 点击 “Next”,进入下一步配置。在此步骤中,您需要配置访问的域名(要确保您的域名托管在 Cloudflare)。
  1. 然后,配置要通过内网穿透访问的服务地址。比如,如果您本机通过 Docker 运行了一个 WebUI 服务,端口为 1234,那么这里就填写 http://localhost:1234。保存配置后,尝试通过刚才设置的域名访问服务。
notion image

解决无法通过公网域名访问的问题

在配置过程中,我遇到了这个问题:无法通过刚刚配置的公网域名访问到服务。

原因排查

宿主机上执行 curl http://localhost:1234 可以正常访问服务,但 Cloudflared 容器日志中显示它尝试连接 http://localhost:1234 时访问被拒绝。以下是 AI 给出的分析:

背景:Docker 网络模式

Docker 默认有多种网络模式,其中常用的包括:
  1. Bridge 模式(默认):容器通过一个虚拟网桥与宿主机通信。每个容器都有自己的独立网络命名空间,localhost 只指向容器内部的地址,而不指向宿主机。
  1. Host 模式:容器与宿主机共享网络命名空间,容器直接使用宿主机的网络接口,localhost 在这种模式下指向宿主机的 localhost

问题原因:网络隔离

cloudflared 容器运行在默认的 bridge 模式下时,容器与宿主机的网络是隔离的:
  • bridge 模式下,localhost 对容器来说是它自己的网络命名空间。尝试访问 localhost:15432 实际上是在访问容器内部的 localhost,而不是宿主机的地址。
  • 如果你想在 bridge 网络模式下从容器访问宿主机的服务,不能直接使用 localhost,而是需要通过宿主机在 Docker 网桥中的 IP 地址(通常是 172.17.0.1)来访问。

解决方法:使用 Host 网络模式

当你使用 --network host 启动 cloudflared 时,容器与宿主机共享网络命名空间,意味着:
  • 容器内的 localhost 就等同于宿主机的 localhost
  • 这样一来,cloudflared 能够直接访问宿主机上运行的 WebUI 服务,因为它们共享相同的网络环境。

因此,在配置过程中第 3 步的命令中,需要进行如下调整:
  • 添加 -d 参数使容器在后台运行。
  • 添加 -network host 参数使容器与宿主机共享网络命名空间。
 

© Cheney Wang 2024