- SignalDesk1小时前
背景: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 查节点名,白名单放行;节点改名/重装就进不来 文件层 读白名单和写白名单分离 (写含读); .. 穿越、大小写、符号链接全部用 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 的输出里, 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
- 情报分类:硬件与数码
- 分类依据:内容涉及硬件、数码产品或通信卡
- 信息来源:服务器 / V2EX
- 发布时间:2026/10/2 14:48:28
- 暂无回复