跳到主要内容

把 localhost:3000 绑定到自己的域名:Cloudflare Tunnel、ngrok、frp 与 Tailscale Funnel 对比

Rainy
雨落无声,代码成诗 —— 致力于技术与艺术的极致平衡
Rainy
13 MIN READ•... VIEWS

本地开发最常见的需求是:应用跑在 localhost:3000,但你希望外部的人、Webhook 平台、手机真机、客户预览环境或远程同事能通过一个公网 HTTPS 地址访问它。

如果只是临时调试,ngrok http 3000 足够快。如果你已经有自己的域名,并且希望长期用 dev.example.com 指到本机服务,Cloudflare Tunnel 通常是更稳的选择:不需要路由器端口转发,不需要本机有公网 IP,也不需要把家庭或办公室网络直接暴露到公网。


一句话选择​

场景推荐特点
最快调试ngrok一条命令把 localhost:3000 暴露出去。免费版可以使用账号分配的 dev domain,但免费版不能选择或保留自己的自定义域名。
有自己的域名,想稳定用Cloudflare Tunnel最推荐。可以把 dev.example.com 指到本机 localhost:3000,不用开路由器端口,也不暴露公网 IP。Cloudflare 官方文档支持通过 public hostname 把公网域名路由到本地服务。
自建、可控、可放国内云服务器frp需要一台有公网 IP 的 VPS。支持 HTTP、HTTPS、TCP、UDP,可以用自己的域名转发到内网服务。
已有 Tailscale 网络Tailscale Funnel可以把本机服务暴露到公网 HTTPS,更偏 Tailscale 生态。官方仍标为 beta,并且公网域名主要是 tailnet-name.ts.net 体系。

我的默认建议:

  1. 只测一次 Webhook:用 ngrok。
  2. 想长期把 dev.example.com、preview.example.com 绑定到本机:用 Cloudflare Tunnel。
  3. 想完全自管入口、日志、带宽、国内访问链路:用 frp 加一台 VPS。
  4. 团队已经在 Tailscale 里,且接受 *.ts.net 域名和 beta 状态:用 Tailscale Funnel。

核心对比​

维度ngrokCloudflare TunnelfrpTailscale Funnel
是否需要公网 VPS不需要不需要需要不需要
是否支持自己的域名支持,但自定义域名属于付费能力支持,域名需要接入 Cloudflare支持,DNS 指到自己的 VPS不适合自定义域名,主要使用 tailnet 域名
免费临时域名有账号分配的 dev domainQuick Tunnel 可生成 trycloudflare.com 随机域名取决于你的 VPS 和域名使用 Tailscale Funnel URL
适合长期稳定入口中等,取决于套餐和域名能力强强,但要自己运维中等,受生态和限制影响
典型协议HTTP、HTTPS、TCP、TLSHTTP/HTTPS 公网应用最顺手;非 HTTP 服务通常需要客户端侧 cloudflaredHTTP、HTTPS、TCP、UDPTLS 加密连接,官方限制端口为 443、8443、10000
运维复杂度低低到中中到高低到中
安全入口能力ngrok policy、basic auth、OAuth 等可叠加 Cloudflare Access、WAF、DDoS 防护、DNS、证书需要自己做认证、TLS、限流和审计依赖 Tailscale ACL、Funnel node attribute 和 HTTPS
最适合临时 Demo、Webhook 调试自有域名稳定预览、团队开发环境自托管、国内 VPS、非 HTTP 端口转发已有 Tailscale tailnet 的轻量公开分享

这里的关键差异不是“谁能穿透内网”,而是谁来持有公网入口:

公网入口越托管,越省事;越自建,越可控。


Cloudflare Tunnel 的工作方式​

Cloudflare Tunnel 的核心组件是 cloudflared。它运行在你的机器上,主动向 Cloudflare 建立出站连接。公网用户访问 dev.example.com 时,请求先到 Cloudflare,再沿着这条隧道转发到本机 localhost:3000。

这和传统端口映射不一样:

传统端口映射Cloudflare Tunnel
路由器或安全组开放公网端口本机只需要能主动访问 Cloudflare
公网能看到你的源站 IP源站 IP 不需要公开
HTTPS、证书、DDoS、WAF 要自己处理可以复用 Cloudflare 的边缘能力
家庭宽带、公司 NAT、动态 IP 容易麻烦对 NAT 和动态 IP 更友好

前提条件:

  1. 有 Cloudflare 账号。
  2. 你的域名已经接入 Cloudflare DNS。
  3. 本机或服务器可以访问外网,并能运行 cloudflared。
  4. 你的本地应用已经在 http://localhost:3000 正常工作。

安装 cloudflared​

如果你通过 Cloudflare Dashboard 创建 Tunnel,页面会根据系统生成安装和运行命令,直接复制执行即可。这是最省心的路径。

手动安装可以按系统选择:

# macOS
brew install cloudflared

# Debian / Ubuntu
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt-get update && sudo apt-get install cloudflared

# RHEL / CentOS / Fedora 系
curl -fsSl https://pkg.cloudflare.com/cloudflared.repo | sudo tee /etc/yum.repos.d/cloudflared.repo
sudo yum update && sudo yum install cloudflared

确认安装:

cloudflared --version

Docker 也可以直接运行:

docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token <TUNNEL_TOKEN>

最快试用:Quick Tunnel​

如果只是临时看一下效果,不需要账号和自定义域名,可以先跑 Quick Tunnel:

# 先启动你的本地项目
npm run start

# 另开一个终端
cloudflared tunnel --url http://localhost:3000

它会生成一个随机的 trycloudflare.com 子域名。这个模式适合临时测试,不适合长期入口:Cloudflare 官方文档说明 Quick Tunnel 面向测试,并且有并发请求和部分能力限制。

只要你想使用自己的 dev.example.com,就应该创建正式 Tunnel。


方式一:Dashboard 创建 Tunnel​

这是推荐给大多数人的方式,因为 token、服务安装命令、Tunnel 健康状态都在页面里。

1. 启动本地应用​

以 Docusaurus 或普通前端项目为例:

npm run start

确认本机可以访问:

curl -I http://localhost:3000

2. 创建 Tunnel​

进入 Cloudflare Dashboard:

  1. 打开 Networking -> Tunnels。
  2. 选择 Create Tunnel。
  3. 输入名称,比如 rainlib-dev。
  4. 选择运行 cloudflared 的操作系统和 CPU 架构。
  5. 复制页面给出的 install/run 命令,在本机执行。
  6. 等待 Tunnel 状态变成 Healthy。

Dashboard 模式通常会给出类似下面的服务安装命令:

sudo cloudflared service install <TUNNEL_TOKEN>

这个 token 是敏感凭证,不要提交到 Git,也不要发到聊天群。

3. 添加公网 Hostname​

在 Tunnel 详情页的 Routes 中添加 route:

字段示例
TypePublished application
Subdomaindev
Domainexample.com
Service URLhttp://localhost:3000

保存后,Cloudflare 会把 https://dev.example.com 路由到本机服务。浏览器打开:

https://dev.example.com

如果你的应用在另一台内网机器上,也可以把 Service URL 写成:

http://192.168.1.20:3000

前提是运行 cloudflared 的机器能访问这个内网地址。


方式二:CLI 本地配置 Tunnel​

如果你希望配置文件可审计、可备份,或者不想把所有规则都放在 Dashboard 里,可以使用 locally-managed tunnel。

1. 登录 Cloudflare​

cloudflared tunnel login

命令会打开浏览器,让你登录 Cloudflare 并选择域名。完成后,本机会生成 cert.pem。

2. 创建命名 Tunnel​

cloudflared tunnel create rainlib-dev
cloudflared tunnel list

创建成功后会得到 Tunnel UUID,并在 ~/.cloudflared/ 下生成凭证文件。

3. 写配置文件​

创建 ~/.cloudflared/config.yml:

tunnel: <Tunnel-UUID>
credentials-file: /Users/<you>/.cloudflared/<Tunnel-UUID>.json

ingress:
- hostname: dev.example.com
service: http://localhost:3000
- service: http_status:404

Linux 上路径通常是:

credentials-file: /home/<you>/.cloudflared/<Tunnel-UUID>.json

注意最后一条 catch-all 规则。Cloudflare 文档要求包含兜底 ingress 规则,否则未匹配的请求不知道该如何处理。这里用 http_status:404 是最干净的默认值。

4. 创建 DNS 路由​

cloudflared tunnel route dns rainlib-dev dev.example.com

这会创建一个 CNAME,指向类似 <Tunnel-UUID>.cfargotunnel.com 的目标。

5. 前台运行测试​

cloudflared tunnel run rainlib-dev

浏览器访问:

https://dev.example.com

6. 服务化运行​

macOS 登录后自动运行:

cloudflared service install

macOS 开机运行:

sudo cloudflared service install
sudo launchctl start com.cloudflare.cloudflared

Linux systemd:

cloudflared service install
systemctl start cloudflared
systemctl status cloudflared

如果你用 sudo 安装 Linux service,要注意 $HOME 可能变成 /root。配置文件在普通用户目录时,应显式指定:

sudo cloudflared --config /home/<USER>/.cloudflared/config.yml service install
sudo systemctl restart cloudflared

Cloudflare Tunnel 常见配置​

多个子域名​

tunnel: <Tunnel-UUID>
credentials-file: /Users/<you>/.cloudflared/<Tunnel-UUID>.json

ingress:
- hostname: dev.example.com
service: http://localhost:3000
- hostname: api-dev.example.com
service: http://localhost:8080
- hostname: admin-dev.example.com
service: http://localhost:9000
- service: http_status:404

匹配路径​

ingress:
- hostname: dev.example.com
path: /api/*
service: http://localhost:8080
- hostname: dev.example.com
service: http://localhost:3000
- service: http_status:404

转发到局域网服务​

ingress:
- hostname: nas.example.com
service: http://192.168.1.50:5000
- service: http_status:404

不要把 NAS、数据库、管理后台裸露到公网。至少叠加 Cloudflare Access、强认证、IP 限制或应用自身登录。


安全建议​

Cloudflare Tunnel 解决的是“公网入口如何到达本机”,不是“你的应用是否应该被任何人访问”。

建议最少做这些事:

  1. 使用独立子域名,比如 dev.example.com,不要直接占用主站根域名。
  2. 本机服务保持监听 127.0.0.1 即可,cloudflared 在同一台机器时不需要应用监听 0.0.0.0。
  3. 不要把 Tunnel token、cert.pem、credentials JSON 提交到仓库。
  4. 预览站、后台、API 文档、调试面板建议加 Cloudflare Access。
  5. 如果只是给 Webhook 平台调用,优先限制路径、加签名校验、检查来源。
  6. 对长期运行的 Tunnel 配置监控和重启策略,避免电脑睡眠后入口不可用。

排障清单​

现象排查方向
502 Bad Gateway本地服务没有启动,端口写错,或者 cloudflared 机器访问不到 localhost:3000。
Tunnel 不健康检查 cloudflared 是否在运行,网络是否能访问 Cloudflare,受限网络下留意出站端口 7844。
域名打不开检查域名是否已接入 Cloudflare,CNAME 是否创建,Tunnel route 是否绑定到了正确 hostname。
本地能访问,公网访问样式或接口异常检查应用里的 baseUrl、CORS、allowed hosts、回调地址和 cookie domain。
HMR 或 WebSocket 异常开发服务器可能需要允许外部 host,或者需要检查 HTTPS、WebSocket 地址和代理头。
service 启动后配置不生效重启 cloudflared service,并确认 service 读取的是你编辑的那个 config.yml。

ngrok 怎么用​

ngrok 最适合“马上给一个公网地址”:

ngrok config add-authtoken <NGROK_AUTHTOKEN>
ngrok http 3000

如果你有可用的 ngrok 域名:

ngrok http 3000 --url https://example.ngrok.app

ngrok 的优点是极快、跨平台、调试体验好,适合 Webhook、本地 Demo、短时间联调。限制是免费版域名能力有限:官方 Domains 文档说明,免费账号可以使用自动分配的 dev domain;选择或保留自定义域名需要付费计划,自带域名属于更高套餐能力。


frp 怎么配置​

frp 的模式是你自己准备一台有公网 IP 的 VPS,公网入口由 frps 持有,本机运行 frpc 主动连出去。

VPS 上的 frps.toml:

bindPort = 7000
vhostHTTPPort = 80
vhostHTTPSPort = 443

启动:

./frps -c ./frps.toml

本机 frpc.toml:

serverAddr = "x.x.x.x"
serverPort = 7000

[[proxies]]
name = "web"
type = "http"
localIP = "127.0.0.1"
localPort = 3000
customDomains = ["dev.example.com"]

启动:

./frpc -c ./frpc.toml

DNS 配置:

dev.example.com A x.x.x.x

frp 的优点是自托管、协议支持广、成本可控,适合你已经有云服务器、希望走国内线路、需要 TCP/UDP 或更多代理能力的场景。代价是你要自己处理 VPS 安全、系统更新、TLS 证书、日志、限流、鉴权和进程守护。


Tailscale Funnel 怎么看​

Tailscale Funnel 适合已经使用 Tailscale 的团队:你可以把本机服务通过公网 HTTPS 暴露出去,让不在 tailnet 里的用户也能访问。

典型命令形态:

tailscale serve --bg 3000
tailscale funnel 443 on

它的边界也很明确:

  1. 官方文档仍标为 beta。
  2. 需要 Tailscale 版本、MagicDNS、HTTPS 证书和 tailnet policy 中的 Funnel node attribute。
  3. Funnel 只能使用 tailnet 的 DNS 名称,比如 machine.tailnet-name.ts.net。
  4. 官方限制监听端口为 443、8443、10000。
  5. 更适合 Tailscale 生态里的分享,不是“把任意自有域名稳定绑定到 localhost”的首选。

如果你的诉求是 dev.example.com -> localhost:3000,Cloudflare Tunnel 更直接。


最终建议​

你想要什么直接选
今天马上给别人看本地页面ngrok
把自己的域名长期指向本机开发服务Cloudflare Tunnel
有 VPS,想完全自管入口和转发规则frp
团队已经在 Tailscale,并接受 beta 和 ts.net 域名Tailscale Funnel

对个人开发者和小团队来说,Cloudflare Tunnel 是最均衡的方案:配置比 frp 少,域名能力比 ngrok 免费版稳定,安全能力又比简单端口转发完整。它尤其适合把 dev.example.com、preview.example.com、webhook-dev.example.com 这类开发入口长期挂到本机或内网机器上。


参考资料​

Logo
RainLib

探索技术、设计与分布式系统的边界。构建面向未来的开发者工具。

留言与建议

© 2026 RainLib. 为未来构建。(Built for the Future)
版权所有。
系统正常