背景: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 命令也是在你电脑上执行的,手机连的是你的电脑,我只是借道发指令
几个关键点:
延迟极低:Tailscale 是点对点加密隧道(能直连就直连),请求都在"虚拟局域网"里跑,一个读文件请求往返几十毫秒 Muse 看不见你的屏幕:桥没有截屏能力,它看到的只是文件内容和命令输出的文本 关窗口即断连:桥是你双击 bat 启动的,关掉黑窗口服务就停了,控制权一直在你手里 为什么要经 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
结论:凡是依赖对端环境的行为,先在本地桩测,别消耗用户的耐心。
五、交互式控制台 黑窗口不是一次性脚本,而是一个 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 。 六、使用方法(给朋友的极简版)
两台电脑都装 Tailscale,登录同一个账号 被控的 Windows 电脑装 Python 3 (官网下载,勾选 Add to PATH ) 把 pc-bridge.py 和 run-bridge-py.bat 放到同一个目录
用记事本改 bat 开头:set ALLOW_NODE=你的控制端节点名 set ALLOW_READ=C:\Users\你 ← 只读目录,逗号分隔多个 set ALLOW_WRITE=D:\work ← 可写目录,留空=不给写 set ALLOW_CMD=hdc,git,go,javac,java,python
双击 bat ,黑窗口保持开着(关了桥就断) 控制端经 Tailscale IP 访问 http://<对端 IP>:18743/health
七、适用边界
✅ 适合:远程调试自己的电脑、拉日志、自动化运维、给父母修电脑 ❌ 不适合:公网直接暴露(务必只绑 Tailscale 内网);对抗专业攻击者(节点私钥丢了就全丢) ⚠️ 写权限 + 命令执行 = 完全控制,只给自己信任的节点,路径白名单能小就小
一句话总结:一个只有一个文件的 Python 小桥,把云端的 Muse 和本地电脑接成一条链路——读写、编译、调试全打通。杀软逼出来的零依赖方案,安全靠"内网 + 节点身份"两层兜底,白名单能小则小,控制权始终攥在本地这一端。 八、✅最后欢迎一起白嫖 10 亿 Token 俺的邀请码:1EQBVV (快速助记:1 亿扣币薇薇)