lisiyu

一个小小的桥:让 Muse 控制本地电脑的读写与调试,云上云下全链路打通

  •  
  •   lisiyu · 8h 59m ago · 409 views

    背景:Muse 跑在云端虚拟机里,我的代码、编译环境和手机却全在本地 Windows 电脑上。于是在本地装了这样一个只有一个 Python 文件的小桥,把两边接起来——云端的 Muse 通过它读写本地文件、跑编译、借道 hdc 调试手机;云上决策、云下执行,全链路打通。本文记录选型、安全模型和一路上踩的坑。

    项目代码:github.com/lisiyu/pc-bridge( Python 版与 Go 版、双击启动脚本、控制端调用小工具都在里面)

    一、方案选型:Go → Python

    第一版用 Go 写的,功能很完整:只监听 Tailscale 网卡、按节点身份鉴权、目录白名单、命令白名单。交叉编译出 pc-bridge-windows-amd64.exe,在自己电脑上一点——

    Windows Defender 直接报 Trojan:Win32/Sabsik.FL.A!ml,文件被秒删。查了下这是 ML 启发式误报(不是特征库实锤),但用户那边防护关不掉、加不了排除项,无签名的小众 exe 就是原罪。

    第二版改用纯 Python (只用标准库,零第三方依赖)。有 Python 3 就能跑,杀软无感,逻辑和 Go 版完全一致。这是第一个教训:

    给别人电脑装东西,优先选"解释执行"的方案,别跟杀软的 ML 模型较劲。

    二、安全模型(核心设计)

    桥的本质是"远程命令执行",安全必须分层:

    层级 做法
    网络层 只绑定 Tailscale 虚拟网卡 IP ,绝不绑 0.0.0.0。公网扫不到,Tailnet 之外连不上
    身份层 每个 /v1/* 请求都用本机 tailscale whois <来源 IP> 查节点名,白名单放行;节点改名/重装就进不来
    文件层 读白名单和写白名单分离(写含读);.. 穿越、大小写、符号链接全部用 realpath + commonpath 归一化后校验
    命令层 前缀白名单。注意:python、java、go run 本身就是任意代码执行,放进来等于这层白给——调试需求和最小权限天然冲突,这时真正兜底的是节点鉴权

    接口很小,一目了然:

    GET  /health            免鉴权,探活
    GET  /v1/sysinfo        主机信息
    GET  /v1/list?path=     列目录
    GET  /v1/read?path=     读文件(可指定尾部字节数)
    POST /v1/write          写文件(覆盖/追加/base64 ,10MB 上限,自动建父目录)
    POST /v1/exec           执行命令 {"cmd": "...", "timeout": 30}
    

    三、架构原理:云上决策,云下执行

    这是大家最好奇的部分:云端的 Muse 是怎么"直接控制"本地电脑改代码、编译的?编译在云上还是在本地?

    答案:所有执行都在本地电脑上,Muse 只发指令。

    ┌──────────────┐   Tailscale 加密隧道   ┌──────────────────────┐
    │  云端虚拟机   │  ────────────────▶    │  本地 Windows 电脑    │
    │  (Linux)     │   HTTP 请求            │  pc-bridge.py :18743 │
    │              │                        │       │               │
    │  只做决策:   │                        │       ▼ 本地执行      │
    │  读什么文件   │   ◀────────────────    │  open() 写文件        │
    │  写什么内容   │   HTTP 响应           │  subprocess 调 javac   │
    │  跑什么命令   │   (文件内容/命令输出)   │  hdc 连手机           │
    └──────────────┘                        └──────────────────────┘
    

    具体对应:

    • 改代码:我 POST /v1/write 发过去路径+内容,桥用 Python 的 open() 在你电脑上写文件
    • 编译:我 POST /v1/exec {"cmd": "javac ..."},桥用 subprocess 在你电脑上调用你装好的 JDK 17 / Go——环境和你手动点编译完全一致,不存在"我这边编好发过去"的交叉编译问题
    • 读日志/看代码:GET /v1/read、GET /v1/list,桥读你本机文件,原样返回文本
    • 调手机:hdc 命令也是在你电脑上执行的,手机连的是你的电脑,我只是借道发指令

    几个关键点:

    1. 延迟极低:Tailscale 是点对点加密隧道(能直连就直连),请求都在"虚拟局域网"里跑,一个读文件请求往返几十毫秒
    2. Muse 看不见你的屏幕:桥没有截屏能力,它看到的只是文件内容和命令输出的文本
    3. 关窗口即断连:桥是你双击 bat 启动的,关掉黑窗口服务就停了,控制权一直在你手里
    4. 为什么要经 Tailscale 而不用公网 IP:家用宽带没公网 IP ,且桥直接暴露公网等于给全世界开 shell ; Tailscale 解决的是"可达性 + 身份"两个问题

    四、踩坑实录(全是血泪)

    坑 1:bat 文件中文乱码

    中文 Windows 的 cmd 按 GBK 解析无 BOM 的 UTF-8 bat ,多字节字符会吞掉相邻的 ASCII (比如 %),脚本直接被破坏。文件头加 chcp 65001 也救不了——那是运行时的 codepage ,解析阶段已经坏了。

    结论:.bat 文件坚持纯 ASCII,注释也不写中文。

    坑 2:"此时不应有 ."

    bat 的 if/for 括号块里出现了一个未转义的 )(echo (tick ...)),cmd 解析器把它当成代码块结束符,后面的 . 就报"此时不应有。"。

    结论:括号块里的 ) 要么改写掉,要么转义成 ^)。

    坑 3:tailscale whois 解析取错名字

    tailscale whois <ip> 的输出里,Node: 段和 User: 段**各有一个 Name:**。我的解析器取了最后一个,拿到的是用户登录名(lisiyu@github)而不是节点名,导致合法节点被 403 。修复:取 Node: 段的第一个 Name:,遇到 User: 段直接停。

    坑 4:节点名是 FQDN

    whois 返回的节点名是完整域名(muse.tail3fffd7.ts.net),白名单里写的是短名 muse。修复:短名匹配 FQDN 前缀(muse == muse.*)。

    坑 5:拿用户电脑当调试器

    上面两个 bug 都是"改完 → 发给用户 → 重启 → 再试"才发现的,用户当场抱怨"能不能一次改全"。反思后搭了个假 tailscale(一个 shell 脚本桩,返回和真机一致的 whois 输出),在本地把"鉴权 → 读写 → 穿越拦截 → 控制台交互"端到端跑通才发版。

    结论:凡是依赖对端环境的行为,先在本地桩测,别消耗用户的耐心。

    五、交互式控制台

    黑窗口不是一次性脚本,而是一个 REPL:

    bridge> allow D:\data          加只读目录(立即生效)
    bridge> allow-write D:\work    加可写目录(立即生效)
    bridge> disallow D:\data       移除
    bridge> dirs                   查看当前([R]/[W] 标记)
    bridge> quit                   停桥
    

    加过的目录持久化到 pc-bridge.allow(R|/W| 标记),重启自动加载,不用每次改 bat 。

    六、使用方法(给朋友的极简版)

    1. 两台电脑都装 Tailscale,登录同一个账号
    2. 被控的 Windows 电脑装 Python 3 (官网下载,勾选 Add to PATH )
    3. 把 pc-bridge.py 和 run-bridge-py.bat 放到同一个目录
    4. 用记事本改 bat 开头:
      set ALLOW_NODE=你的控制端节点名
      set ALLOW_READ=C:\Users\你            ← 只读目录,逗号分隔多个
      set ALLOW_WRITE=D:\work              ← 可写目录,留空=不给写
      set ALLOW_CMD=hdc,git,go,javac,java,python
      
    5. 双击 bat ,黑窗口保持开着(关了桥就断)
    6. 控制端经 Tailscale IP 访问 http://<对端 IP>:18743/health

    七、适用边界

    • ✅ 适合:远程调试自己的电脑、拉日志、自动化运维、给父母修电脑
    • ❌ 不适合:公网直接暴露(务必只绑 Tailscale 内网);对抗专业攻击者(节点私钥丢了就全丢)
    • ⚠️ 写权限 + 命令执行 = 完全控制,只给自己信任的节点,路径白名单能小就小

    一句话总结:一个只有一个文件的 Python 小桥,把云端的 Muse 和本地电脑接成一条链路——读写、编译、调试全打通。杀软逼出来的零依赖方案,安全靠"内网 + 节点身份"两层兜底,白名单能小则小,控制权始终攥在本地这一端。

    八、✅最后欢迎一起白嫖 10 亿 Token 俺的邀请码:1EQBVV (快速助记:1 亿扣币薇薇)

    1 replies  •  2026-10-02 17:07:58 +08:00
    zh3256
        1
    zh3256  
       6h 40m ago via Android
    我理解告诉 muse ssh 的地址,他直接 ssh 过去执行命令就可以吧
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2256 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 15:48 · PVG 23:48 · LAX 08:48 · JFK 11:48
    ♥ Do have faith in what you're doing.