利用 Cloudflare Tunnel 与 WebSocket 入站实现内网服务的零公网 IP 暴露
前言
在日常开发和自托管场景中,我们经常遇到这样的问题:手头有一台没有公网 IP 的机器(家宽 NAS、校园网服务器、云上容器等),想把它上面的服务安全地暴露出去,又不想在路由器上开端口转发。本文分享我实践过的一套方案:Cloudflare Tunnel(Argo)+ WebSocket 类入站代理,实现零公网 IP、零端口开放的服务暴露,并记录了排查“隧道通但业务不通”问题的完整思路。
一、整体架构
用户客户端
│ TLS
▼
Cloudflare Edge(域名解析,代理开启)
│ WSS 加密隧道(cloudflared 主动外连,无需入站端口)
▼
本机 cloudflared 进程
│ HTTP 回源 localhost:PORT
▼
服务端应用(支持 WebSocket 路由分发)
核心思想:让云端主动"出站"连接 Cloudflare。cloudflared 与边缘节点建立长连接后,所有访问指定域名的流量都会通过这条隧道回源到本机,防火墙只需要允许出站 7844 端口即可。
二、实施步骤
1. 创建隧道
在 Cloudflare Zero Trust 控制台创建 Tunnel,得到 token,在服务器上运行:
cloudflared tunnel --no-autoupdate --protocol http2 run --token <TOKEN>
然后把域名(如 app.example.com)绑定到该隧道,回源地址填 http://localhost:8001。
2. 服务端多协议复用一个端口
为了在一台机器、一个隧道端口上承载多种业务路由,我用了一个带 fallback 的入站设计:
-
主入站监听
8001,按路径分发:-
/vless-argo→ 内部 3002(WebSocket) -
/vmess-argo→ 内部 3003(WebSocket) -
/trojan-argo→ 内部 3004(WebSocket) -
其他流量 → 直接回落 3001
-
这样 Cloudflare 回源只打一个端口,内部路由互不干扰,运维上非常清爽。
3. 客户端配置要点
以 vmess + ws + tls 为例,客户端关键参数:
| 参数 | 值 |
|---|---|
| 地址 | 优选域名/IP(如 saas 类优选域名) |
| 端口 | 443 |
| 传输 | WebSocket |
| path | /vmess-argo?ed=2560(ed 参数启用 0-RTT) |
| Host/SNI | 隧道域名 |
注意:优选域名解析到的是 Cloudflare 边缘节点,不是你的服务器;真正的回源靠 SNI + Host 匹配到隧道。
三、踩坑记录:隧道通、节点不通
这是最有价值的一部分。我遇到过控制台显示连接器在线、curl https://隧道域名/ 也有响应,但实际业务握手失败的情况。排查思路如下:
1. 先分层定位
# ① 隧道层:本地回源是否正常
curl -i -H "Upgrade: websocket" -H "Connection: Upgrade" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Version: 13" http://127.0.0.1:8001/vmess-argo
# 期望 101
# ② 公网层:走域名测试
curl -i --http1.1 -H "Upgrade: websocket" ... https://app.example.com/vmess-argo
-
① 通、② 不通 → 问题在 Cloudflare 回源配置(回源端口、ingress 规则)
-
① 就不通 → 问题在本机服务(大概率是入站没起来)
2. 本机入站“静默失败”的经典陷阱
服务端用 nohup app -c config.json >/dev/null 2>&1 & 启动,如果 8001 被其他进程占用,核心会启动失败,但日志被吞掉了,主进程还活着,看起来一切正常。
解决:启动后必须验证端口真的在监听:
ss -tlnp | grep -E ':(8001|3001|3002|3003|3004)'
我在脚本里加了预检逻辑:启动前逐端口尝试绑定,被占用直接报错提示换端口;启动后轮询探测端口进入 LISTEN 状态才继续。自此再没被这个问题坑过。
3. 530 vs 502 的含义
-
530:隧道本身没连上(cloudflared 进程死了或 token 失效)→ 查 cloudflared
-
502:隧道通,但回源失败(服务没监听 / 端口不对)→ 查本机服务和回源配置
记住这两个码,排查速度能快一倍。
四、稳定性建议
-
固定隧道 + 固定回源端口:临时隧道(trycloudflare.com)域名每次重启都变,务必用固定隧道。
-
子进程看护:cloudflared 和业务核心用 systemd 或 pm2 托管,并配置崩溃自动重启。
-
高位端口防冲突:回源端口选 50000+ 的高位端口,避开容器环境常见的 8000/8080。
-
WebSocket 路径加随机化:路径里带一段随机串,减少被扫描器探测的概率。
结语
整套方案零公网 IP、零端口暴露,所有流量都走 TLS 加密的 Cloudflare 网络,适合自托管面板、家庭 NAS 服务等场景。最大的心得是:“进程在跑”不等于“服务可用”,端口监听验证和分层 curl 探测是排障的两个基本功。希望这篇分享能帮你少踩几个坑。
- 点赞
- 收藏
- 关注作者
评论(0)