Windows 上用 cloudflared 建隧道:从命令行到系统服务的踩坑记录

Nov 8, 2026 required to read

背景

在 Windows 上把本地服务通过 Cloudflare Tunnel 暴露到公网,cloudflared 本身并不复杂,但一旦从“手动 run”切换到“Windows 系统服务”,就会遇到几个比较隐蔽的坑。

本文记录一次完整流程:安装、纯命令行创建隧道、写 config.yml、安装为 Windows 服务,以及服务模式下配置路径、ImagePath 和重启卡死的问题。

安装 cloudflared

可以通过 Scoop 或 Winget 安装:

scoop install cloudflared

或 powershell:

winget install -e --id Cloudflare.cloudflared

安装后确认命令可用:

where cloudflared
cloudflared --version

纯命令行创建本地管理隧道

这里使用“本地管理隧道”模式:隧道配置保存在本地 config.yml,通过命令行创建和管理。

1. 登录授权

cloudflared tunnel login

浏览器会打开 Cloudflare 授权页面。授权成功后,本地会生成 cert.pem,它是后续命令行操作的身份凭证。

2. 创建隧道

隧道名称只能包含小写字母、数字和连字符,长度 1 到 63,且在同一账户下唯一。例如:

cloudflared tunnel create xu-newhome

执行后会生成一个凭证 JSON 文件,文件名通常包含隧道 UUID。

3. 编写 config.yml

在默认配置目录 %USERPROFILE%\.cloudflared 下创建 config.yml,例如:

tunnel: xu-newhome
credentials-file: C:\Users\Administrator\.cloudflared\c7d942f8-65b4-4c57-800b-5e08af87556b.json

ingress:

- hostname: app.example.com
  service: http://localhost:8000
- service: http_status:404

注意:

  • credentials-file 建议使用绝对路径。
  • ingress 最后一条必须是回退规则,例如 http_status:404。
  • 如果 config.yml 放在自定义位置,运行时要加 s--config 指定完整路径。

4. 添加 DNS 路由

cloudflared tunnel route dns xu-newhome app.example.com

这一步会在 Cloudflare 上创建 CNAME,把域名指向隧道。

5. 手动运行测试

cloudflared tunnel --config .\.cloudflared\config.yml run xu-newhome

日志中出现 Registered tunnel connection,说明隧道已经连上 Cloudflare。

安装为 Windows 系统服务

手动 run 的进程关掉终端就断了,因此可以安装为 Windows 服务:

cloudflared service install

如果提示服务已存在,说明这台机器上已经有 cloudflared 服务。Cloudflare 的限制是:同一台机器只能运行一个 cloudflared 服务实例。不同机器、不同 NAS 各自运行不冲突。

服务模式的三个大坑

坑一:服务读取的 config.yml 不是用户目录下的那个

手动运行时,你用的是:

C:\Users\Administrator\.cloudflared\config.yml

但 Windows 服务以 SYSTEM 账户运行,默认读取的是:

C:\Windows\System32\config\systemprofile\.cloudflared\config.yml

如果只把配置写在用户目录,服务虽然“启动了”,但并没有加载你期望的隧道配置。

解决方式:把 config.yml 和凭证 JSON 复制到系统配置目录:

mkdir C:\Windows\System32\config\systemprofile\.cloudflared -Force

copy C:\Users\Administrator\.cloudflared\config.yml `
  C:\Windows\System32\config\systemprofile\.cloudflared\config.yml

copy C:\Users\Administrator\.cloudflared\c7d942f8-65b4-4c57-800b-5e08af87556b.json `
  C:\Windows\System32\config\systemprofile\.cloudflared\

并把系统配置目录里的 config.yml 中 credentials-file 改成绝对路径:

credentials-file: C:\Windows\System32\config\systemprofile\.cloudflared\c7d942f8-65b4-4c57-800b-5e08af87556b.json

坑二:服务的 ImagePath 只指向 exe,缺少运行参数

查看服务注册表:

Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Cloudflared' -Name ImagePath

如果输出只是:

C:\Users\Administrator\scoop\apps\cloudflared\current\cloudflared.exe

说明它只启动了程序本身,没有告诉 cloudflared 要运行哪个隧道、用哪个配置文件,服务会启动失败。

需要手动修正 ImagePath,补上 tunnel --config ... run 参数。以管理员身份执行:

$cloudflaredExe = "C:\Users\Administrator\scoop\apps\cloudflared\current\cloudflared.exe"
$configFile = "C:\Windows\System32\config\systemprofile\.cloudflared\config.yml"

$newImagePath = "`"$cloudflaredExe`" tunnel --config `"$configFile`" run"

reg add "HKLM\SYSTEM\CurrentControlSet\Services\Cloudflared" `
  /v ImagePath /t REG_EXPAND_SZ /d "$newImagePath" /f

验证:

(Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Cloudflared' -Name ImagePath).ImagePath

输出应类似:

"C:\Users\Administrator\scoop\apps\cloudflared\current\cloudflared.exe" tunnel --config "C:\Windows\System32\config\systemprofile\.cloudflared\config.yml" run

坑三:Restart-Service 卡在“Waiting for service to stop”

cloudflared 在 Windows 服务模式下有一个已知问题:有时无法正常响应停止信号,Restart-Service cloudflared 会一直卡住。管理员权限也解决不了,需要强制结束进程。

先查服务 PID:

sc queryex cloudflared

然后强制结束:

taskkill /f /pid <PID>

或者直接结束所有 cloudflared 进程:

Get-Process -Name cloudflared -ErrorAction SilentlyContinue | Stop-Process -Force

确认进程消失后,再启动服务:

Start-Service cloudflared

以后修改配置后的推荐重启流程是:

Get-Process cloudflared -ErrorAction SilentlyContinue | Stop-Process -Force
Start-Sleep -Seconds 2
Start-Service cloudflared

不要依赖 Restart-Service 自动完成两步。

验证隧道是否真的生效

服务启动成功不等于网站可访问。建议按顺序检查:

  1. 查看 cloudflared 日志,确认出现 Registered tunnel connection。
  2. 登录 Cloudflare Dashboard,进入 Networking → Tunnels,确认隧道状态为 Healthy,Connector 数量正常。
  3. 浏览器访问 config.yml 中配置的 hostname。
  4. 检查 Cloudflare DNS 中该域名的 CNAME 是否指向:
<隧道UUID>.cfargotunnel.com

如果 Dashboard 正常、日志也显示连接成功,但网站打不开,优先检查 DNS 记录是否被旧记录占用,以及本地服务地址和端口是否正确。

多台 NAS 使用 cloudflared 会冲突吗

不会。不同设备各自运行 cloudflared 互不影响。

需要注意:

  • 同一台机器只能运行一个 cloudflared 服务实例。
  • 不同设备建议分别创建独立隧道,或用不同路由规则区分。
  • 不要把同一个隧道的凭证复制到两台设备上同时运行,否则 Cloudflare 会把流量随机分发到两台设备,相当于负载均衡,而不是主备。

安全提醒

cert.pem 权限很高,持有它可以管理账户下的所有隧道。不要随意复制到不信任的设备。如果必须在新设备上操作,更安全的做法是在那台设备上重新执行:

cloudflared tunnel login

生成新的凭证。

常用命令速查

# 查看隧道列表
cloudflared tunnel list

# 查看隧道详情
cloudflared tunnel info xu-newhome

# 删除隧道
cloudflared tunnel delete xu-newhome

# 清理失效连接
cloudflared tunnel cleanup xu-newhome

# 安装服务
cloudflared service install

# 卸载服务
cloudflared service uninstall

# 强制停止进程后启动服务
Get-Process cloudflared -ErrorAction SilentlyContinue | Stop-Process -Force
Start-Service cloudflared

小结

Windows 上使用 cloudflared 的关键,是区分“手动运行”和“系统服务”两种模式:

  • 手动运行读用户目录配置;
  • 系统服务读 SYSTEM 账户配置目录;
  • 服务 ImagePath 必须带 tunnel --config ... run 参数;
  • 重启卡住时直接强制结束进程,再单独启动服务。
  • 把这几个点处理好,cloudflared 作为 Windows 服务长期运行还是比较稳定的。