Cloudflare Tunnel 内网穿透实战:从部署到自建运维大屏
在一台没有公网 IP 的机器上(MUSE),用 Cloudflare Tunnel 把本地服务暴露到公网,并顺手搭一个带密码保护的 macOS 风格运维大屏。本文记录完整过程和两个关键避坑技巧。
一、为什么选 Cloudflare Tunnel
传统内网穿透方案(frp、ngrok 等)要么需要一台有公网 IP 的中转服务器,要么有流量/带宽限制。Cloudflare Tunnel 的优势很明显:
- 免费且不限流量:个人使用完全够用
- 无需公网 IP:被穿透的机器只需能出站访问 Cloudflare
- 自动 HTTPS:Cloudflare 边缘自动签发证书
- 支持任意 TCP 服务:HTTP、SSH、RDP 都可以
原理很简单:在内网机器上运行 cloudflared 客户端,它主动向 Cloudflare 边缘建立长连接;公网请求先到 Cloudflare,再经这条长连接转发回内网。全程不需要入站端口。
二、创建隧道
-
登录 Cloudflare Dashboard → 左侧 Zero Trust → Networks → Tunnels
-
点击 Create a tunnel,选 Cloudflared 类型,起个名字(如
my-tunnel) -
复制生成的 Tunnel Token(一长串 JWT),后面客户端要用
-
在 Public Hostname 里添加路由,例如:
- Hostname:
panel.example.com - Service:
http://localhost:8080
意思是:访问
https://panel.example.com的请求,会被转发到运行cloudflared那台机器的本地 8080 端口。 - Hostname:
⚠️ 注意:Tunnel Token 相当于这台机器的接入凭证,不要发到公开场合,也不要提交到 Git 仓库。
三、安装 cloudflared(可以直接发提示词让 muse 自动安装执行测试)
Debian/Ubuntu 官方仓库安装:
# 添加 Cloudflare GPG key
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-public-v2.gpg \
| sudo tee /usr/share/keyrings/cloudflare-public-v2.gpg >/dev/null
# 添加 apt 源
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-public-v2.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
也可以直接下载二进制,解压即用:
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared
chmod +x cloudflared
四、启动隧道(基础版)
最简单的启动方式:
cloudflared tunnel --no-autoupdate run --token <你的Tunnel Token>
正常情况下几秒钟就能看到 Registered tunnel connection 的日志,说明隧道已建立。此时访问你在 Dashboard 配的域名,应该就能打开内网服务了。
但如果你在受限网络环境(沙箱、某些云主机、公司内网),可能会遇到下面两个坑。
五、避坑一:DNS 解析失败
症状
日志里反复出现:
ERR Failed to fetch features ... lookup cfd-features.argotunnel.com on [xxx]:53: server misbehaving
ERR ... Could not lookup srv records on _v2-origintunneld._tcp.argotunnel.com
原因
cloudflared 启动时需要通过 DNS SRV 记录发现 Cloudflare 边缘节点(region1.v2.argotunnel.com 等)。某些 DNS 服务器(沙箱环境、劣质 DNS)不支持或错误处理 SRV 查询,导致发现失败。
解法:绕过 DNS,直接指定边缘 IP
先用 DNS-over-HTTPS(走 1.1.1.1)查出边缘节点的真实 IP:
curl -s "https://1.1.1.1/dns-query?name=region1.v2.argotunnel.com&type=A" \
-H "accept: application/dns-json"
返回类似:
{"Answer": [{"data": "198.41.192.27"}, {"data": "198.41.192.227"}, ...]}
然后用 --edge 参数直接指定,跳过 DNS 发现:
cloudflared tunnel --no-autoupdate \
--edge 198.41.192.27:7844 \
run --token <你的Tunnel Token>
💡 这个技巧也适用于其他 DNS 被污染/劫持的环境。边缘 IP 段相对固定(
198.41.192.0/20等),即使换一个也能用。
六、避坑二:UDP 被封禁
症状
指定 --edge 后出现:
ERR Failed to dial a quic connection ... write udp [::]:xxxxx->198.41.192.27:7844: sendmsg: operation not permitted
原因
cloudflared 默认用 QUIC(基于 UDP) 连接边缘节点。很多受限环境直接禁了 UDP 出站,导致 QUIC 握手失败。
解法:强制使用 HTTP/2(TCP)
cloudflared tunnel --no-autoupdate \
--edge 198.41.192.27:7844 \
--protocol http2 \
run --token <你的Tunnel Token>
看到 Registered tunnel connection ... protocol=http2 就说明成功了。HTTP/2 走 TCP 443,虽然延迟略高于 QUIC,但稳定性完全没问题。
完整启动命令(受限环境版)
nohup cloudflared tunnel --no-autoupdate \
--edge 198.41.192.27:7844 \
--protocol http2 \
run --token <你的Tunnel Token> > /tmp/cloudflared.log 2>&1 &
七、自建运维大屏
隧道通了之后,我在 8080 端口搭了一个运维大屏,用 Python 标准库写了个极简后端(无第三方依赖):
from http.server import HTTPServer, BaseHTTPRequestHandler
import json, subprocess
def sys_stats():
cpu = subprocess.getoutput("top -bn1 | grep '%Cpu' | awk '{print $2+$4}'")
mem = subprocess.getoutput("free | awk '/Mem/{printf \"%.1f\", $3/$2*100}'")
disk = subprocess.getoutput("df / | tail -1 | awk '{print $5}' | tr -d '%'")
return {"cpu": cpu, "mem": mem, "disk": disk}
class H(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/api/stats":
d = json.dumps(sys_stats()).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers(); self.wfile.write(d)
# ... 其他路由
前端用原生 HTML/CSS/JS,定时 fetch('/api/stats') 刷新。功能包括:
- 📊 实时监控:CPU、内存、磁盘使用率(带颜色预警)、系统负载
- 🧩 服务状态:关键进程是否存活
- 🖥️ 多机管理:通过 SSH 把另一台 VPS 的状态也接进来一起看
八、给大屏加密码保护
公网可访问的页面必须加验证。实现很简单:
- 后端
/api/login接口校验密码,成功返回一个随机 token - 前端登录后把 token 存
sessionStorage,每次请求带X-Token头 - 后端对所有
/api/*接口校验 token
import secrets
_tokens = set()
# 登录
if data.get("password") == "你的密码":
tk = secrets.token_hex(16)
_tokens.add(tk)
return {"ok": True, "token": tk}
💡 生产环境建议用更完善的方案(如 Cloudflare Access),这里是轻量自用的折中。
九、macOS 液态玻璃风格美化
最后一步是颜值。参考 macOS Tahoe 的 Liquid Glass 设计语言,核心就两行 CSS:
.glass {
background: rgba(255, 255, 255, 0.55);
backdrop-filter: blur(30px) saturate(180%);
-webkit-backdrop-filter: blur(30px) saturate(180%);
border: 1px solid rgba(255, 255, 255, 0.45);
border-radius: 28px;
box-shadow: 0 12px 48px rgba(0, 0, 0, 0.12);
}
登录页再配一张随机背景图(比如 https://random.mozuiapp.com/?day=random 这类随机图 API),每次打开都是不同的风景,毛玻璃卡片浮在上面,效果非常惊艳。
要点:
- 大圆角:卡片 20-28px,按钮/输入框 14-16px
- 高饱和模糊:
saturate(180%)让背景色彩更通透 - 细腻阴影:多层柔光阴影营造悬浮感
- 苹果式排版:
-apple-system字体,标题letter-spacing: -0.03em
十、总结
| 步骤 | 要点 |
|---|---|
| 创建隧道 | Dashboard → Zero Trust → Tunnels,配好域名路由 |
| 安装客户端 | 官方 apt 源或直接下载二进制 |
| DNS 坑 | DoH 查边缘 IP + --edge 绕过 |
| UDP 坑 | --protocol http2 走 TCP |
| 运维大屏 | Python 标准库后端 + 原生前端,零依赖 |
| 安全 | 登录页 + API token 校验 |
| 美化 | 毛玻璃 + 随机背景图 + 大圆角 |
整套方案跑下来,一台没有公网 IP 的机器也能拥有公网可访问、安全、好看的运维面板。如果你也在受限网络环境折腾过内网穿透,希望这两个 --edge 和 --protocol 的小技巧能帮你省点时间。
最后还有没有申请到 MUSE 的小伙伴提供一个可用的免费的注册方法,简单实用:
1、谷歌浏览器搜索 VeePN插件 可免费试用
2、选择美国俄勒冈节点并启用
3、登录 muse.ai 网站正常注册,选择生日,注意大于 18 岁
4、绑定银行卡预扣费(后期会返还)
5、设置中填写我的邀请码 URFRH3
6、安卓手机下载:Muse AI 第三方下载地址 (APKMirror):https://www.apkmirror.com/apk/facebook-2/muse-from-meta/muse-from-meta-9-0-0-23-178-release/muse-from-meta-9-0-0-23-178-android-apk-download/
这样你就拥有了一个带一台 vps 的智能伙伴了,还有永久的 10 亿 token 够大家用好久了,祝好运
本文涉及的域名、IP 均为示例,实际部署请替换为自己的配置。
有截图吗
看看效果
对哟 看看UI界面
简单的界面抛砖引玉,自己需要什么界面,直接让它直接给你做就行了哈哈
每1-2小时 Muse 的机器就会轮转怎么解决的?
@koujiang #3 这个界面的背景图/颜色 能分享一下吗
非常优秀的项目
@felix96 #5 https://random.mozuiapp.com/ 一个基于 bing 的随机图 api
怎么保活呢
@Cus #8
全部恢复 ✅
✅ 隧道已重新连接(Cloudflare 后台稍后会显示正常运行)
✅ https://muse.mozuiapp.com/ 公网访问正常(200)
✅ token 已存加密文件,看门狗会用它自动重启
✅ 看门狗每 5 分钟巡检,VM 再重启也能自己恢复
以后掉线会自动自愈,主人不用管了。
好资源,感谢推荐