夜雨聆风学习资料网

ARTICLE · 1083685

Muse AI 给你的云电脑只能出不能进?看我如何用反向 SSH 把方向盘拿了回来

Muse AI 给你的云电脑只能出不能进?看我如何用反向 SSH 把方向盘拿了回来

最近 Meta 发布了个人 AI agent Muse。和 ChatGPT、Claude 最大的不同是:每个用户都有一台专属的云端虚拟机,agent 就住在里面,替你收发邮件、订票、填表,你关掉 App 它还在继续干活。

用了几天,我有个强烈的感受:这台电脑是 agent 的,方向盘不在我手里。

作为一个老网工,第一反应是:先 SSH 进去再说。

⚠️ 声明:本文只讨论技术实现。长期挂隧道是否符合平台的使用条款,请读者自行确认。

一、Muse 为什么给每个人一台电脑?

按 Meta 官方的说法:只会生成文字的模型出错,最多是答错一句话;能操作邮箱、电商、订票系统的 agent 一旦出错,就会变成真实发生的动作。所以 Muse 的思路是先给 agent 一台隔离的专属电脑,把犯错的范围关在里面。

这台电脑里还有第二层保护:一个独立的 Sentinel 进程负责审批 Muse 的每一个动作,任何操作不经过它都到不了互联网,Muse 本身也看不到你的密码和支付方式。

对比
Muse
Claude / ChatGPT
执行环境
每人一台常驻 VM
临时沙箱,用完即重置
你离开后
继续干活,可定时
以对话为单位
状态保留
文件、登录态长期保留
多随会话结束
定位
有工位的助理
随叫随到的专家

二、实测:这台机器的底

项目
实测
系统
Ubuntu 24.04,内核 7.0
虚拟化
systemd-nspawn 容器(VM 内的运行单元)
CPU
2 vCPU,AMD EPYC,x86_64
内存
标称 8G,实际可用约 2.5G
系统盘
/ 分区 7.5G,重启即重置
持久盘
/home/hatch 100G,唯一长期保存处
GPU
无
网络
只出不进,出口为 Cloudflare

标称 8G,为什么只能用 2.5G?

执行 free,显示已用 5.4G。但用 ps 把所有进程加起来,只有 0.5G 左右。

顺着 /proc/meminfo 逐项核对,最后在 /proc/vmstat 里找到了答案:

nr_balloon_pages 800478balloon_inflate  800478balloon_deflate  0

截图是写稿后重测的:气球已涨到 843590 页(约 3.2G)。气球大小由宿主机动态调整,可用内存会随之浮动。

800478 页 × 4KiB ≈ 3GiB,这部分是被宿主机通过 virtio-balloon(内存气球) 收走的。气球驱动在 VM 里占住一部分内存、交还给宿主机,在 VM 内部看是「已用」,但不属于任何进程。再减去平台自身组件的约 0.8G,真正留给你的只有 2.5G 左右。

这是云上超售内存的常见手法:标称配置是上限,不是保证。 你也可以在自己的机器上用这三行命令验证:

free -hgrep -E '^(MemTotal|MemAvailable|AnonPages|Cached):' /proc/meminfogrep -i balloon /proc/vmstat

这台机器是故意做弱的:推理、浏览器池这类吃资源的部分都被拆了出去,放在别处当服务,VM 里只留下编排和工作区。

三、为什么 Tailscale 行不通

Muse 的 VM 里预装了 Tailscale,在我的 tailnet 控制台里也能看到它在线。本以为 tailscale set --ssh 一条命令就能搞定,结果:

  • • tailscale version、tailscale set 全部报错,这是一个封装过的精简版;
  • • 平台明确说明这台机器是 client-only,不接受任何入站连接;
  • • 在 VM 里直接访问 100.x 的 tailnet 地址会被拦截,只能走平台代理。

对照官方架构就能理解:凭证、Sentinel、网络代理这些安全敏感组件,都放在 agent 所在的运行单元之外。你在容器里是 root,但网络出口不归你管。

既然进不去,那就让它自己出来。

四、架构:反向 SSH 隧道

三个安全设计:

  1. 1. VPS 上的隧道端口只监听 127.0.0.1,从公网扫描不到。
  2. 2. Muse 用专用的 tunnel 账户登录 VPS。 这个账户没有 shell,密钥被限制为只能在 2222 这一个端口上做反向转发。就算密钥泄露,也登录不了 VPS。
  3. 3. 全链路只用密钥认证,密码登录全部关闭。

五、分步配置

🖥 = 在 VPS 上执行;🤖 = 在 Muse 上执行(直接把命令贴给 Muse 的 AI 让它跑);💻 = 在 Windows 笔记本上执行

第 0 步:开启 Muse 出站权限

在 Muse 网页端进入 Settings → Permissions,打开 Outbound SSH 和 Other TCP connections。

第 1 步:VPS 基线检查与保活

# 🖥 先核实 VPS 的真实公网 IP(别凭记忆!)curl -s ifconfig.me# 确认只允许密钥登录、不开放网关端口sudo sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication|allowtcpforwarding|gatewayports)'# 保活:对端消失后,约 90 秒自动释放隧道端口echo -e "ClientAliveInterval 30\nClientAliveCountMax 3" | sudo tee /etc/ssh/sshd_config.d/10-keepalive.confsudo sshd -t && sudo systemctl reload ssh

第 2 步:VPS 创建隧道专用账户

# 🖥sudo useradd -m -s /usr/sbin/nologin tunnelsudo install -d -m 700 -o tunnel -g tunnel /home/tunnel/.ssh

第 3 步:Muse 部署 sshd 与自愈脚本

# 🤖D=/home/hatch/.muse-ssh; mkdir -p $D; chmod 700 $D[ -f $D/ssh_host_ed25519_key ] || ssh-keygen -t ed25519 -N '' -f $D/ssh_host_ed25519_key[ -f $D/tunnel_key ] || ssh-keygen -t ed25519 -N '' -f $D/tunnel_key -C muse-vmcat > $D/sshd_config <<'EOF'Port 2022ListenAddress 127.0.0.1HostKey /home/hatch/.muse-ssh/ssh_host_ed25519_keyPidFile /home/hatch/.muse-ssh/sshd.pidAuthorizedKeysFile /home/hatch/.muse-ssh/authorized_keysPermitRootLogin prohibit-passwordPasswordAuthentication noKbdInteractiveAuthentication noStrictModes noUsePAM noSubsystem sftp internal-sftpEOFcat > $D/boot.sh <<'EOF'#!/bin/bashD=/home/hatch/.muse-sshVPS=tunnel@<VPS_IP>[ -x /usr/sbin/sshd ] || { sudo apt-get update -qq && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openssh-server; } >>$D/boot.log 2>&1install -d -m 0755 /run/sshdpgrep -f "[s]shd -f $D/sshd_config" >/dev/null || /usr/sbin/sshd -f $D/sshd_configpgrep -f "[R] 127.0.0.1:2222" >/dev/null || nohup bash -c "while true; do  ssh -N -i $D/tunnel_key -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \    -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=accept-new \    -o UserKnownHostsFile=$D/known_hosts \    -R 127.0.0.1:2222:127.0.0.1:2022 $VPS  sleep 5; done" >>$D/tunnel.log 2>&1 &EOFchmod +x $D/boot.shtouch $D/authorized_keys; chmod 600 $D/authorized_keyscat $D/tunnel_key.pub

脚本的几个设计点:

  • • host key 放在持久盘:重启后指纹不变,客户端不会告警。
  • • 系统盘被重置时自动重装 openssh-server。
  • • 隧道断开后每 5 秒自动重连。
  • • [s]shd 和 [R] 的写法:防止 pgrep 匹配到调用者自己的命令行(见踩坑清单)。

第 4 步:VPS 写入 Muse 公钥,并限制权限

# 🖥(把 AAAA... 换成第 3 步最后输出的公钥)echo 'restrict,port-forwarding,permitlisten="127.0.0.1:2222" ssh-ed25519 AAAA... muse-vm' \ | sudo tee /home/tunnel/.ssh/authorized_keyssudo chown tunnel:tunnel /home/tunnel/.ssh/authorized_keyssudo chmod 600 /home/tunnel/.ssh/authorized_keys

第 5 步:笔记本生成密钥,交给 Muse

# 💻 PowerShellssh-keygen -t ed25519 -C my-laptoptype $env:USERPROFILE\.ssh\id_ed25519.pub

把输出的公钥贴给 Muse 的 AI,让它写进 authorized_keys,然后执行 boot.sh。在 VPS 上检查:

# 🖥sudo ss -tlnp | grep 2222      # 应该只看到 127.0.0.1:2222

六、客户端连接

Windows OpenSSH / VS Code

在 C:\Users\<你>\.ssh\config 里追加:

Host oci  HostName <VPS 的 Tailscale 名称>  User ubuntu  IdentityFile ~/.ssh/oci_vps.keyHost muse-vm  HostName 127.0.0.1  Port 2222  User root  ProxyJump oci  HostKeyAlias muse-vm  IdentityFile ~/.ssh/id_ed25519  ServerAliveInterval 30

之后执行 ssh muse-vm 即可进入,VS Code Remote-SSH 里也可以直接选择。

💡 Windows 私钥权限过宽时,OpenSSH 会拒绝使用。可以这样收紧:icacls <私钥> /inheritance:r 和 icacls <私钥> /grant:r "$($env:USERNAME):(R)"

MobaXterm

新建 SSH 会话:目标填 127.0.0.1:2222,用户 root;Advanced SSH settings → Use private key,选择 id_ed25519;Network settings → SSH gateway (jump host) 填 VPS 地址和用户 ubuntu,选择 VPS 私钥。

SecureCRT

先建一个 VPS 会话,在 Authentication 里把 PublicKey 调到首位,选择 VPS 私钥;再建 muse-vm 会话,目标填 127.0.0.1:2222;在 Connection → Firewall → Select Session,指定前面的 VPS 会话作为跳板。

七、连上之后能干什么

场景 1:人和 AI 共用一台工作机

这是最核心的价值:

  • • 用 VS Code 打开 agent 正在写的项目。agent 卡住了我接手,我改完了交还给它。
  • • 它说「已修复」,我自己用 git diff、查日志来确认。
  • • 用 MobaXterm 侧边栏拖拽文件,不用再在对话框里绕来绕去。

这次搭建本身就是一次人机协作。隧道断线后,Muse 的 AI 自己翻日志定位到了根因:VM 重启后,VPS 上的旧会话还占着 2222 端口。判断完全正确。但它也说过「用 tunnel 账户登录 VPS 就能进来」,这是错的,因为那个账户根本没有 shell。

AI 能干活,但方向盘还得在人手里。

场景 2:OCI 负责调度,Muse 负责干活

我的 OCI 是 ARM 架构,Muse 是 x86 架构,正好互补。在 VPS 上生成一把专用密钥,加入 Muse 的授权列表后,VPS 就能免密调度 Muse:

# 🖥ssh muse "nproc; free -h"

OCI 负责编排和存储,Muse 负责算力。 Muse 休眠时,VPS 检测到 2222 端口不通,就自动降级到本机执行。适合 x86 构建、CPU 版语音转写这类轻量任务。

场景 3:美国侧的网络观测点

# 🤖curl -s ipinfo.io

出口在美国,但 AS 号属于 Cloudflare,说明平台的出站流量统一经过 Cloudflare。可以用它从美国视角测 DNS、TLS、首包延迟。但要注意:这个出口是共享 IP 池,不固定,而且会被网站识别为代理,不适合当固定出口,也不适合登录重要账号。

不适合做的事

  • • 重计算:可用内存只有 2.5G,又没有 swap,很容易触发 OOM。
  • • 对外提供服务:只能出站,而且可能休眠。
  • • 存放公司或客户数据。

八、踩坑清单

坑
解法
Muse 自带 Tailscale 只能出站
改走反向 SSH 隧道
pgrep 匹配到自己,sshd 不启动
进程名写成 [s]shd
容器里缺少 /run/sshd
脚本里先建好目录
Muse 重启后旧会话占住 2222
VPS 开保活,残留会话手动清
grep Accepted 误匹配配置项
改搜 Accepted publickey
新版 OpenSSH 拒绝 ssh-rsa
换 ed25519 密钥
free 与进程内存对不上
查 /proc/vmstat 的内存气球

九、重启恢复与回退

Muse 重启后:让 AI 执行 /home/hatch/.muse-ssh/boot.sh,等 1 到 2 分钟即可重新连接。

完全回退:

# 🤖pkill -f "[R] 127.0.0.1:2222"; kill $(cat /home/hatch/.muse-ssh/sshd.pid)rm -rf /home/hatch/.muse-ssh
# 🖥sudo pkill -u tunnel; sudo userdel -r tunnel

写在最后

ChatGPT 和 Claude 像随叫随到的专家;Muse 像一个有工位的助理,工位就是那台 VM。它带来了持续性和隔离,但也是一个被刻意做小、刻意封闭的工位。

一条反向隧道、一个受限账户、一个自愈脚本,就是给自己也配了一把进这个工位的钥匙。能进去看、能动手改、能随时收回,才叫可控。

想自己上手试试 Muse?我的邀请码:K53N8S

如果对你有帮助,欢迎转发给同样在折腾 AI agent 的朋友。

相关学习资料