Cloudflare Tunnel 把内网服务暴露出去

以前想让外网访问家里的服务,路子无非两条:要么在路由器上做端口映射并暴露公网 IP,要么租一台有公网 IP 的 VPS 做反向代理。

这两种做法都有个共同的毛病——你确实在公网上开了一个入口。哪怕只转发 443,扫描器也会很快找上门。

Cloudflare Tunnel 换了思路:连接是从内网主动向外建立的,公网侧根本不存在可以扫描的入站端口。

原理

访客 → Cloudflare 边缘节点 →(已经建好的长连接)→ cloudflared → localhost:3000

cloudflared 进程在你这台机器上跑着,启动时主动连到 Cloudflare 并保持一条隧道。外部请求到达边缘节点后,顺着这条已建立的连接回传进来。

所以:

  • 路由器上不需要开任何端口
  • 不需要公网 IP,NAT 后面就行
  • 出口流量,防火墙通常不会拦

基本用法

先登录并创建隧道:

cloudflared tunnel login
cloudflared tunnel create my-blog

然后把本地服务和域名绑起来:

cloudflared tunnel route dns my-blog blog.example.com

配置文件 ~/.cloudflared/config.yml:

tunnel: ff19965a-1b58-45e6-91bc-6d1d2202293c
credentials-file: /home/user/.cloudflared/ff19965a-....json

ingress:
  - hostname: blog.example.com
    service: http://localhost:3000

  # 兜底规则必须放最后,否则 cloudflared 会拒绝启动
  - service: http_status:404

最后那个 http_status:404 是必需的——少了它 cloudflared 会启动失败,因为 ingress 规则要求有一个不带 hostname 的兜底项。

几个实际会踩的点

DNS 记录要指向隧道。 用 tunnel route dns 命令加出来的记录是一条 CNAME,指向 <隧道ID>.cfargotunnel.com,而且必须保持**橙色云朵(已代理)**打开。手动改成 DNS only 就废了。

Windows 上装成服务。 想让隧道开机自启、后台常驻:

cloudflared service install

区分「隧道」和「DNS」两套权限。 Cloudflare 的 API Token 权限粒度很细,一个能改 DNS 的 Token 未必能管理隧道——Account → Cloudflare Tunnel → Edit 是另一个独立权限。报 9109 的时候先怀疑这个,而不是怀疑 Token 写错了。

和 Pages 怎么选

Cloudflare Tunnel Cloudflare Pages
需要常开的机器 是 否
适合动态服务 是 否(纯静态)
全球加速 依赖源站 原生 CDN
运维成本 中 几乎为零

结论挺简单:静态博客用 Pages,动态服务才上 Tunnel。 让一台机器整年开着只为托管几页 Markdown,实在没必要。

不过 Tunnel 有个 Pages 替代不了的优势:本地开发环境可以挂个域名直接给同事看,改完代码刷新即生效,不用重新部署。

← 返回文章列表

评论