远程访问与客户端
机器(在设置编辑器中称为工作区)只存在于一台 Mac 上,但想要操作它的人并不总是坐在那台 Mac 前。Bromure Agentic Coding 可以远程访问,而每条远程路径都经过同一道可选、默认关闭的 SSH 前门。打开它,你就有三种接入方式:任何人都可以从任意终端通过 ssh 登录并进入一个菜单;你可以从命令行管理这道前门本身;而富客户端——另一台运行本应用的 Mac,或 iPhone、iPad、Apple Vision Pro 上的 Bromure Remote——可以连接并在实时窗口中镜像整个实例——其会话、房间和总机、机器、终端和看板。
富客户端有两种方式连到服务器。在同一网络中,你直接按地址添加它。从其他任何地方,你登录一个 bromure.io 账户,并从目录中挑选服务器:两台设备由 bromure.io 相互引荐,随后以点对点通信,无需端口转发、无需 VPN、也无需记住任何地址——而且一旦登录,你自己的设备便会彼此授权,因此连接是免密码的,无需手动配置密钥。
本章涵盖在宿主机上启用远程访问、各个接入点、富客户端如何镜像远程主机(按地址和通过 bromure.io)、编辑远程主机的偏好设置、iPhone、iPad 和 Vision Pro 客户端、访问远程虚拟机内的服务、将开发服务器暴露到互联网,以及保障这一切安全的安全模型。设备群规模的注册和云遥测是完全不同的系统——请参阅企业版。完整的命令参考位于 CLI、API 与 MCP。
三种接入方式
下面的一切都取决于 SSH 前门是否已启用(默认关闭)。一旦它开始运行,同一台服务器便会同时服务这三类受众:
| 接入方式 | 使用者 | 你得到什么 |
|---|---|---|
| 普通 SSH | 任意终端前的人(ssh -p 2222 you@mac) | 远程菜单——一个 curses 风格的 TUI。永远无法进入原始 shell。 |
bromure-cli remote CLI | 你,在宿主机本机上 | 管理前门:启用/禁用、密钥、状态。参见在宿主机上启用远程访问。 |
| 富客户端 | 另一台运行本应用的 Mac,或 iOS / iPadOS / visionOS 上的 Bromure Remote | 远程实例的实时镜像,支持双向编辑——在局域网上按地址连接,或从任何地方通过 bromure.io 账户连接。 |
该服务器是嵌入式的——它是内置于应用中的 Apple swift-nio-ssh 库,而不是 macOS 自带的 sshd。这一区别很重要:因为应用运行自己的服务器,它可以通过 OpenDirectory 验证你的 macOS 账户密码,而无需你在系统设置中启用远程登录,也无需管理员权限。它仅监听运行应用的那个确切的 macOS 用户,并强制每一次交互式登录都进入远程菜单。唯一面向机器的例外是富客户端使用的四条白名单命令(bromure-fatclient/1 control、forward <ip> <port>、forward-udp <ip> 和 browser-mcp <vm>);人类输入的其他任何内容都会被当作登录处理并落入菜单。
注意: 远程访问窗口将该服务器描述为“应用自有的系统 SSH 服务器实例”。更准确地说,它是一个嵌入式 swift-nio-ssh 服务器,刻意不是 macOS 的
sshd——正是这一点让它无需远程登录或管理员权限即可工作。
在宿主机上启用远程访问
远程访问在你开启之前始终处于关闭状态,并且可以通过两种等价方式管理:远程访问窗口或 bromure-cli remote CLI。两者写入同一处,因此在其中一处所做的更改会反映到另一处,并实时生效。
远程访问窗口
打开 Bromure Agentic Coding(应用名菜单)→ 远程访问…。窗口标题为远程访问。一个绿色或灰色圆点显示 sshd running 或 sshd stopped;当服务器运行时,标题下方会出现一个可复制的连接字符串,形如 ssh -p <port> <user>@<host>。
| 区域 | 字段 | 用途 | 默认值 |
|---|---|---|---|
| 标题 | 启用基于 SSH 的远程访问 | 启动和停止服务器。 | 关闭 |
| 监听器 | 绑定 IP | 监听哪个网络接口。0.0.0.0 = 所有接口;127.0.0.1 = 仅本机 Mac。 | 0.0.0.0 |
| 监听器 | 端口 | 监听器 TCP 端口;必须 ≥ 1024(非 root 进程无法绑定特权端口)。 | 2222 |
| 认证 | macOS 账户密码 | 接受运行应用的用户的 macOS 登录密码(通过 OpenDirectory 验证)。 | 开启 |
| 认证 | 公钥 | 接受下方授权密钥列表中的密钥。 | 开启 |
| 服务器主机密钥 | 指纹 | 服务器自身的 ed25519 主机密钥指纹,用于带外验证。首次使用前显示为**(首次启用时生成)**。 | — |
| 授权公钥 | 列表 | 已注册的 ssh-ed25519 / ecdsa 公钥。粘贴一行密钥即可添加;点击垃圾桶图标移除。为空时显示未注册任何密钥。 | 空 |
编辑绑定 IP 或端口后按回车键使更改实时生效。认证区域标注根据 <user> 验证——运行 bromure-ac 的用户。,以便清楚谁的密码可以打开这扇门。
警告: 至少必须保留一种启用的认证方式——你不能同时关闭密码和公钥认证。粘贴无效密钥会被拒绝,并显示不是有效的公钥。添加或移除授权密钥会重启监听器,从而中断任何正在进行的连接。
bromure-cli remote CLI
该 CLI 通过应用仅限所有者的控制套接字与运行中的应用通信,因此应用始终是唯一的事实来源。对于你通过既有 shell 连上的无头 Mac,这是启用访问的最快方式。
| 命令 | 作用 |
|---|---|
bromure-cli remote(或 remote status) | 打印启用/运行状态、绑定与端口、认证方式、主机密钥指纹、登录用户、现成的连接字符串,以及带编号的授权密钥列表。 |
bromure-cli remote enable [--port N] [--bind IP] [--password|--no-password] [--pubkey|--no-pubkey] | 启动服务器(如有需要会自动拉起应用代理)。默认值:端口 2222、绑定 0.0.0.0、两种认证方式均开启。 |
bromure-cli remote disable | 停止服务器并持久化关闭状态。 |
bromure-cli remote key add <path-or-key-text> | 从文件路径或粘贴的密钥行注册一个公钥;打印其指纹。 |
bromure-cli remote key ls | 列出授权密钥,附带从 1 开始的索引、指纹和注释。 |
bromure-cli remote key rm <index|fingerprint> | 按索引或指纹子串移除密钥。 |
如果你同时传入 --no-password 和 --no-pubkey,remote enable 会拒绝执行;在基础镜像缺失或正在安装时它也会报错。当应用未运行时,status、disable 和 key ls 会打印没有正在运行的 bromure-ac 代理。
注意: 在基础镜像缺失或仍在安装时,服务器不会启动——此时启用会返回一个可操作的错误,而不是悄无声息地无操作。这在启动时和你切换开关时都成立。请先安装或完成安装基础镜像。
主机密钥、指纹与信任
首次启用时,服务器会生成一个 ed25519 主机密钥。它的指纹——显示在服务器主机密钥行以及 bromure-cli remote status 中,形如 256 SHA256:… bromure-ac-remote (ED25519)——正是连接中的客户端用来确认自己接入了正确 Mac 的依据。请把这个指纹交给任何要连接的人(或在富客户端的首次接触面板中自行核对),以防中间人冒充宿主机。关于富客户端如何固定它,参见首次使用时信任。
速率限制
密码尝试按来源 IP 通过令牌桶进行节流:五次全速尝试,随后以约每两秒一次的速度补充令牌,所施加的延迟上限为八秒。尝试只会被延迟,绝不会被拒绝,也没有人会被锁定;一个吵闹的 IP 无法拖慢另一个。公钥认证从不节流。
通过普通 SSH 登录
任何终端都可以用 ssh -p 2222 <user>@<mac> 访问宿主机。连接不会进入 shell,而是落入远程菜单——一个 curses 风格的 TUI(内部为 bromure-ac __remote-menu),它被强制施加于每一次人类登录。永远无法通过它进入原始 shell。
该菜单早于以会话为中心的重新设计,并以机器为核心组织:一个工作区列表,带有实时状态符号(● 运行中、◌ 启动中、⏸ 已挂起、○ 关闭),另有模型(已安装的模型和设备端目录)和 Trace(摘要、主机名、泄漏)部分。你可以在这里:
- 用单屏表单创建工作区,并可通过 Full settings… 进入各面板的设置表单。
- 启动、挂起、终止、重启或删除任意工作区。
- 编辑设置。 机密显示为
•••• (set);将机密留空会保留已存储的值。 - 管理工作树——创建、合并、附加终端或丢弃。
- 生成 SSH 密钥、切换 Fusion 和模型路由,以及浏览追踪摘要。
- 附加到任意 tmux 标签页或正在运行的 Docker 容器。
注: 菜单的设置表单无法编辑模型看板。其模型表单为只读:它列出服务器的提供方(API 密钥或订阅),并说明工作区是否覆盖了全局设置。请在 Mac 上的偏好设置,或镜像的远程偏好设置中选择提供方和模型。
使用方向键导航,回车键选择,q 或 Esc 返回;退出(断开连接)结束会话。选择附加会将终端交给客户机的 tmux;Ctrl-b d 分离回菜单。在附加期间,一个覆盖层组合键(默认 Ctrl-])会弹出一个宿主机侧控制器——切换标签页、打开新标签页、管理工作树、切换 Fusion 或路由、编辑设置、重启、挂起或断开连接——而该按键从不会传到客户机。附加到容器时会提示输入 shell(回车 = sh)。
注: 菜单需要真正的终端。在没有 TTY 的情况下连接,会显示用
ssh -t重新连接的提示。启动冷的工作区时,会先等待客户机的 tmux 会话最多约 20 秒,再进行附加。
覆盖层组合键可在被连接的宿主机 Mac 上通过文件 ~/Library/Application Support/BromureAC/remote/overlay-key 配置——可接受的形式为 C-]、^]、0x1d 或 29——或通过 BROMURE_OVERLAY_KEY 环境变量配置。
使用富客户端镜像远程主机
富客户端会把这台 Mac 上的 Bromure Agentic Coding——或 iPhone、iPad、Apple Vision Pro 上的 Bromure Remote——变成远程实例的实时镜像。在 Mac 上,你会得到一个标题为 Remote — <name> 的完整窗口,外观和操作都与本地主窗口相同:会话主页、房间和总机、机器、任务和自动化看板。你所做的一切都在远程主机上运行,并回传结果。
连接
打开 工作区 › 连接到远程 Bromure…(⇧⌘K)。窗口概括了这一选择:*“镜像另一台运行 Bromure 的 Mac——包括其网格、工作区、标签页和自动化。登录后可随处访问你的服务器,也可以直接通过局域网地址添加。”*两条路径都会进入同一个镜像窗口;区别只在于两台设备如何找到彼此并授权。
注意: SSH 握手会随链路自适应:连接与握手的时间预算会随实测的往返时间伸缩,因此高延迟链路(酒店 Wi-Fi、蜂窝网络、相隔一个大洲)只是连得较慢,而不会超时失败。
按地址(同一网络)
当你知道 Mac 的地址且不需要 bromure.io 账户时,在 LAN 上使用这种方式。
- 在远程 Mac 上,启用远程访问(远程访问窗口或
bromure-cli remote enable)。 - 在这台 Mac 上,点击 +,输入名称(例如
rack mini)、地址、端口(默认2222)和远程用户,然后点击连接。已保存的行会显示user@address:port以及上次连接时间。 - 在首次接触时,一个面板会显示远程主机的 SSH 主机密钥指纹。对照远程主机的远程访问窗口进行核对,然后点击信任并继续。该固定信息会为此端点记住;除非密钥更改,否则后续连接都是静默的,若更改则按钮会变红并显示信任新密钥并继续——这可能是中间人攻击。
- 客户端会先用这台设备的专用密钥尝试公钥认证。如果尚未获得授权,则回退到远程用户的 macOS 登录密码(按钮:登录);密码登录成功后,会通过隧道把这台设备的密钥注册到远程主机,之后每次连接都无需密码。若要在完全不输入密码的情况下预先授权,请点按 显示这台 Mac 的密钥,然后在远程主机上运行
bromure-cli remote key add '<this Mac's key>'。
首次连接后,双击已保存的服务器即可一键重新连接;每一行的上下文菜单提供 连接、编辑… 和 移除。iPhone 和 iPad 上的 Bromure Remote 在 通过地址添加服务器 下提供相同流程。
通过 bromure.io 账户(从任何地方)
登录 bromure.io 可让客户端跨网络访问你的服务器——从咖啡馆的 Wi-Fi 连到家里的 Mac——无需端口转发、无需 VPN,也无需记住任何地址。bromure.io 只负责介绍两台设备,并在无法建立直接路径时中继字节;SSH 会话本身在两者之间始终保持端到端加密。
- 登录。 在 Mac 上,从应用名称菜单选择 登录 bromure.io…,并通过浏览器登录(或展开代码部分,输入六个词的注册码和 设备名称)。在 Bromure Remote 中,从其开始屏幕登录。你注册的每台设备都共享同一个账户。
- 在远程 Mac 上,启用远程访问。只有当某台服务器的前门开启且正在向 bromure.io 发送心跳时,它才会出现在目录中。
- 在客户端上,打开 连接到远程 Bromure…。你的服务器会列在 我的服务器 · bromure.io 下,带有实时在线圆点和最后在线时间。双击其中一台(或选中后点按 连接)。在建立点对点路径——直连、通过路由器端口映射,或经由中继——期间,状态会显示 “Connecting to
<name>via bromure.io…”,随后镜像打开。
在这条路径中,没有要输入的地址、没有主机密钥面板、也没有密码:你自己的设备通过你的账户彼此信任(见下文),主机密钥会被自动固定。
在你自己的设备之间免密码
一旦你登录,你注册的每台设备都会通过你的账户共享其 SSH 身份,因此你的任意设备都能到达你的任意服务器,无需密码,也无需手动 bromure-cli remote key add:
- 每台设备在启动时都会把自己的 SSH 公钥发布到 bromure.io。你的每台服务器(已开启远程访问)会在几秒内获取你各设备的密钥并安装到其
authorized_keys,因此刚注册的设备几乎立即就会获得授权。 - 服务器还会发布它所运行的 macOS 登录账户,因此客户端会自动以正确的用户拨号连接(正是按地址路径要求你填写的那个字段)。
- 密钥仅限于你自己的设备——即使在同一组织内,也绝不属于其他用户。
- 在某台设备上登出会让它退役:它的密钥会从你的服务器上移除,它也会从目录中消失,因此重新登录绝不会留下过时的重复项。闲置 90 天的设备也会停止被授权,直到它下次签到。此外,你还可以从 bromure.io 的 Web 控制台按需登出你的任意设备。
注: 富客户端第一次使用时会生成自己专用的 ed25519 密钥对(注释为
bromure-ac-fatclient)——这就是发布到你账户的密钥。按地址连接时,主机密钥的固定属于端点(address:port),而不是用户,因此编辑已保存服务器的地址或端口会丢弃固定,并再次显示指纹表单;bromure.io 连接则改为通过账户固定对等端的密钥。
镜像窗口
连接成功后,镜像窗口会自动打开。它就是远程 Mac 的会话主页:相同的边栏(会话、房间、总机、任务、自动化、含任何 Kubernetes 集群和注册表的虚拟机)、相同的舞台和相同的标题栏。用 新建会话(⌘N)开始会话、与它聊天、回答它的问题、打开带有聊天网格的房间,或与远程主机的总机对话——这一切都在远程主机上进行,⌘K 命令面板也能使用。
标题栏有与本地窗口相同的控件:用于会话终端的 Linux 胶囊、以机器命名的机器菜单(设置…、机器详情、拷贝 IP 地址、检查跟踪、在独立窗口中打开、重启)、Fusion 闪电图标、显示或隐藏代理式浏览器 (⌃⌘B) 以及 显示或隐藏“文件”面板 (⌃⌘E)。镜像窗口另外添加一个专属控件:网络隧道开关(请参阅系统级网络隧道)。终端会以机器自身的外观呈现。
有几项功能在镜像中的行为比较特殊:
- 设置… 会打开与本地相同的设置编辑器,其背后是清空机密的读取和保留机密的保存(请参阅机密始终留在宿主机)。其模型面板编辑的是该远程机器对远程 Mac 模型设置的覆盖。Generate new SSH key 可正常工作,并会显示新的公钥。
- “文件”面板(⌃⌘E)会通过隧道浏览机器的文件。它取代了早期版本中独立的文件浏览器窗口。请参阅机器。
- 重启 的工作方式与服务器自己的窗口相同:在 重新启动“…”? 之后进行正常重启,或在选择时按住 ⌥ 以强制重启(请参阅重启机器);之后指令会发送到服务器。
- 在独立窗口中打开 会打开一个额外的实时终端窗口,该窗口会在机器停止时自动关闭。
如果远程主机运行的是没有会话 API 的旧版 Bromure,镜像会回退到旧的以机器为中心的布局。
菜单作用于前台的镜像
当镜像窗口是主窗口时,下列菜单项会作用于远程 Mac,而不是这台 Mac:
| 菜单项 | 对被镜像 Mac 的效果 |
|---|---|
| 新建会话…(⌘N) | 打开镜像的新会话屏幕。 |
| 工作区 › 新建房间… | 在远程主机上创建房间。 |
| 下一个房间(⌃⌘R) | 轮流切换远程主机的房间(跳过已归档的房间)。 |
| 工作区 › 基础设施 › 创建 Kubernetes 集群… / 创建镜像仓库… | 在镜像中打开创建表单,因此集群或注册表会在远程主机上创建。 |
| 偏好设置…(⌘,) | 打开以远程主机为对象的偏好设置(见下文)。 |
远程偏好设置
在镜像窗口位于前台时按下 ⌘,,偏好设置会以那台 Mac 的默认值打开,标题为 偏好设置 — <host>。只要有镜像窗口打开,偏好设置顶部的 设置对象: 选择器就能在 此 Mac 和每个已连接的远程主机之间切换;每个对象都有自己的编辑器,因此草稿绝不会在机器之间混用。加载远程设置期间,窗口会显示“正在从 <host> 加载偏好设置…”;如果加载失败,则显示 无法加载远程偏好设置 和 重试。
一切都经由远程主机往返处理:机密到达时为空白,除非你输入新的值,否则会保留原值。模型面板编辑远程主机的全局模型设置——API 密钥会以遮蔽方式显示——而更改会在你点按 存储 时保存;这与本地偏好设置不同,后者的模型看板会随着编辑实时保存(请参阅模型与提供方)。这台 Mac 自己的应用级设置——自动化面板,以及资源中的 工作区子网 和 远程传输 部分——不会为远程主机显示,也不会出现在远程机器的编辑器中。
远程登录提供方
订阅登录可以从客户端端到端完成。Sign in with 提供方 会在远程主机上运行捕获,但提供方的登录页面(或设备代码 URL)会在你的浏览器中打开;对于从不显示 URL 的提供方,客户端会显示登录虚拟机的终端,让你以交互方式完成。从远程机器设置开始的登录,会在你的屏幕上询问范围问题——每个工作区 或 仅此工作区;如果没有人回答,则保持 仅此工作区。从远程偏好设置开始的登录,始终由远程主机上的所有机器共享。登出… 也可以远程操作。
远程使用分支与审查
对于拥有自己文件夹的会话,新建分支…、查看更改 和 合并到 分支 都能在镜像中使用,与在远程主机自己的屏幕上完全相同(请参阅分支与审查)。在 Bromure Remote 中,会话的菜单提供 新建工作树…。
询问被镜像 Mac 上的会话
当这台 Mac 正在镜像远程主机时,这里的会话可以通过 @昵称询问远程主机上的会话:远程会话会出现在撰写框的 @ 列表中,并以其主机名呈现给代理;附加在请求中的文件会经由隧道送进对方的收件箱。回答、方向调整和结束也都沿同一路径返回。反方向——远程主机的代理询问这台 Mac 上的会话——不可用,因为远程主机没有回到客户端的通道。
镜像的内容
镜像会显示每台机器及其实时运行状态、会话和房间、标签页和分支、网格、自动化、编程任务看板、机器详情和健康指标、Docker 仪表板、Kubernetes 集群和注册表、实时交互式终端,以及远程主机的安全事件——这些事件会与这台 Mac 的事件并列显示在安全时间线中,其机器筛选器提供 所有机器、此 Mac 和每台被镜像的主机。设备端模型及其下载都在远程主机上运行,绝不在客户端上。编辑会在每个已连接的客户端上收敛:机器的启动、停止和重启、会话和房间操作、标签页操作、网格编辑(整个布局,最后写入者为准)、自动化编辑、Fusion 开关、Docker 操作、设置保存和文件传输。
镜像通过推送通道(GET /state/subscribe)跟随远程主机,该通道位于经 SSH 隧道连接到远程控制套接字的桥接上;推送通道正常时,客户端只会每 5 秒重新读取一次完整状态作为心跳,如果通道中断则改为每 0.75 秒读取一次。简短的控制调用在每台主机的一条 SSH 连接上多路复用;交互式终端附加则使用各自专用的 SSH 连接,因为多路复用通道会缓冲终端需要立即获得的输出。通过 bromure.io 连接时,同样的桥接和终端流会走点对点路径,镜像的行为完全相同。
聊天也会节省链路。第一次打开远程会话的聊天时,只加载对话中最新的约 1.5 MB;向上滚动到 加载更早的对话 时,才会获取较旧的部分。再次打开的聊天——点回某个会话,或再次显示某个房间——会从已下载的历史开始,只获取新消息。
有几项操作无法从富客户端使用:
- 网格布局编辑需要远程主机上开着 GUI 窗口。完全无界面的远程主机(应用运行中但没有主窗口)会镜像其他所有内容,但无法接受布局更改。
- 从文件导入 SSH 密钥在远程设置编辑器中是隐藏的。
iPhone、iPad 和 Apple Vision Pro 上的 Bromure Remote
Bromure Remote 是纯客户端的镜像,连接方式完全相同(登录并挑选服务器,或按地址添加服务器)。它和 Mac 一样以会话为中心:
- iPhone——一个 会话 列表,并显示需要你处理的会话数量;一个新会话屏幕(“我能帮你做什么?”);以及每个会话各自的屏幕:其聊天、用于终端的 Linux 按钮,以及包含 恢复、重命名…、新建工作树…、机器设置、归档(或 结束并归档)、结束会话 和 删除会话 的菜单。房间会以每个会话一个标签页的方式打开,可左右滑动切换,并附有房间的总机。
- iPad——常驻边栏,包含会话、房间和机器;房间会像在 Mac 上一样显示其聊天网格。
在两者上,列表的顺序都与 Mac 边栏相同:先是 新建会话,正下方是 编码任务 与 自动化,然后是会话。机器分成 虚拟机(附网格)与 Native Machines——远程所连接的 Sidecar Mac,只在有的时候才显示;原生机器提供 新建终端。在 iPad 上,新建会话 会一直显示在可折叠的会话分区上方。
当远程拒绝启动会话时(例如在没有该代理的 Sidecar Mac 上),客户端会显示远程给出的理由,而不是毫无反应。
- Apple Vision Pro——iPad 的布局,再加上空间窗口:可把任何终端固定为独立窗口放在房间中的任何位置、把网格打开为专用的舞台窗口,或用 Pin All as Windows 把整个网格变成浮动窗口。
在房间中,底部的单一撰写框有一个 发给 选择器——房间的总机或其中任一会话——以及附件菜单(照片图库、选择文件、粘贴图片);附件会在发送时上传到目标的机器。在 iPhone 和 iPad 上,当应用在后台时,需要你输入的会话可以通过推送通知找到你;轻点即可打开该会话。这些设备上无法使用模型看板;请在 Mac 上更改模型。
待处理的决策提示
有些操作会在远程主机上引发需要决定的事项——主目录存储升级、基础镜像漂移重置、清除遭入侵的虚拟机、关闭操作的询问、提供方登录的范围问题,或凭据外泄警报(入侵检测器暂停了一台试图泄漏凭据的虚拟机)。这些会以警报形式出现在你的镜像窗口中,你的回答会经由隧道传回。如果提示无人响应,会超时并采取安全的选项。待处理的提示绝不会阻塞远程主机的控制平面:警报显示期间,镜像的其他部分仍保持实时。运行中的代理可能触发的同意提示(凭据使用、供应链直通、护栏写入、提示注入),则由另一条客户机无法伪造的路径处理,详见远程同意处理。
机密始终留在宿主机
机密绝不会跨越链路。当富客户端读取远程机器的设置或远程主机的偏好设置时,每个机密字段到达时都是空白的(模型提供方的 API 密钥以遮蔽后的替代值到达)。保存时,空白或遮蔽的字段表示“保留已存储的值”,输入的值则会替换它。API 密钥、令牌、订阅登录和 MCP 环境机密都留在远程 Mac 上。配对完成后,富客户端只用 SSH 密钥认证——镜像期间不会出现任何密码提示。
访问远程主机虚拟机上的服务
远程工作区的开发服务器位于远程主机网络上的一个私有地址,例如 http://192.168.64.5:3000。Bromure 为你提供两个层级的访问方式——一个自动且限定于浏览器,一个需选择加入且系统级。
浏览器窗格(自动,PAC 限定作用域)
镜像窗口中可折叠的浏览器窗格(标题栏的地球按钮,或 ⌃⌘B)是一台本地 Chromium 虚拟机,其发往远程工作区子网的页面流量会通过 SSH 隧道传输。生成的 PAC(代理自动配置)脚本只把远程子网路由到每台主机专属的 SOCKS 转发器,其余一律 DIRECT,而目标会在远程端解析——因此直接访问远程开发服务器的字面地址 http://192.168.64.x:port 就能工作。远程代理自己的浏览器控制 MCP 流会中继到这个窗格,让远程编程代理操作你正在看的浏览器。
在运行中的远程机器上选中一个会话或机器,然后按 ⌃⌘B。在第一次状态更新送来远程主机的子网、且 SOCKS 转发器启动之前,窗格不会有任何动作(在此之前,日志中会有一行“tunnel not ready”)。其本地浏览器虚拟机固定在子网 192.168.127.0/24(网关 192.168.127.1),因此绝不会与工作区子网冲突。持久化浏览器配置文件保存在这台 Mac 上,以远程机器的 ID 为索引。
注意: 浏览器窗格要求这台 Mac 为 Apple Silicon 且本地已安装浏览器基础镜像。SOCKS 转发器绑定
0.0.0.0(以便浏览器虚拟机能在 vmnet 网关处访问它),但只接受来自环回和固定的192.168.127.x浏览器子网的连接——它绝不是一个开放中继。
SOCKS 转发与固定端口转发
每个已连接的远程主机都会自动获得一个本地 SOCKS5 转发器,绑定于一个临时端口的 0.0.0.0(对等端过滤为环回和 192.168.127.x 浏览器子网)。每一次 CONNECT 都会打开一个 forward <ip> <port> SSH 通道,由远程主机——经由客户机始终开启的 vsock 5010 环回中继——桥接到该客户机自己的 127.0.0.1:<port>。因此,从这台 Mac 上,curl --socks5 127.0.0.1:<port> http://192.168.64.5:3000 会逐字节地到达远程客户机。
对于固定转发,有隐藏的 CLI 管道:bromure-cli __forward <hostID> <localPort> <remoteIP> <remotePort> 用于 ssh -L 风格的转发,bromure-cli __forward-socks <hostID> <localPort> 用于独立的 SOCKS 代理服务器。两者默认都绑定环回,并接受 --bind-all。
警告: 远程主机会拒绝任何目标不是其自身 vmnet 子网上客户机的转发。你无法用转发来访问远程 Mac 本身、它的网关或互联网——只能访问工作区虚拟机。
系统级网络隧道
当你希望任何本地应用——而不只是浏览器窗格——都能通过字面地址访问远程虚拟机时,请用镜像窗口的网络开关(相连圆点图标,标题栏控件中的第一个)启用每台主机的隧道。其工具提示为 启用对远程主机 VM 的直接网络访问(任意本地应用可访问 192.168.x.x)。
一个一次性的特权辅助程序——通过 SMAppService 安装的 launchd 守护进程,无需 sudo——创建一个 utun 接口并将远程子网路由到它,然后把该接口的文件描述符交回给应用。应用中的一个用户态 TCP/UDP 栈会终止每一条流,并使用你的 SSH 身份将其拼接到同样的 SSH 转发通道上。没有 pf 规则,也没有内核转发。
第一次启用它时,一个标题为允许 Bromure 的网络辅助程序的警报会说明这次一次性的 macOS 批准:
- 点击工具栏开关。
- 在警报中,打开系统设置 → 通用 → 登录项,并允许 Bromure Agentic Coding(macOS 会索要一次管理员凭据)。
- 应用会轮询批准(每 2 秒一次,最多 5 分钟),并在批准落地的一刻自动连接。在等待期间,开关工具提示为正在等待“系统设置 › 登录项”中的批准…。
如果远程主机尚未报告其机器子网(尚无任何机器启动),工具提示会显示 正在等待远程实例报告其工作区子网(请启动一个工作区)——点击取消。隧道建立后,工具提示会显示 已开启对远程主机 VM 的直接网络访问——点按以关闭;如果失败,则显示 网络隧道失败——点按以重试。关闭开关会停止隧道,而当最后一台主机停用它时,守护进程会被注销。此设置按主机记住。
注意: 隧道的一次性批准需要一个管理员账户。没有它时,Bromure 会继续通过内置的 SOCKS 路径工作——只有从其他应用访问远程虚拟机时才需要该辅助程序。如果 macOS 直接拒绝注册,一个标题为无法安装网络辅助程序的警报会加以说明,且开关会在下次点击时重试。对远程客户机的
ping会由隧道在本地应答:它确认路由已建立,而非确认客户机存活。
多个远程主机(每次安装独立子网 + 设备群路由)
你可以同时镜像多个远程主机;每个都会打开自己的窗口、SOCKS 转发器以及(可选的)隧道。以前常踩的坑是:历史上每次安装都为其工作区虚拟机使用相同的 192.168.64.0/24 网络,因此两个被镜像的远程主机会通告完全相同的子网,而系统级 VPN 无法区分它们。
每次安装独立子网从根源上解决了这个问题。现在每台 Mac 都会在 172.16.0.0/12 内挑选一个随机的 /24——跳过 Docker 的 172.17–172.20 范围,以及宿主机已经所在的任何 /24——并将它用于其所有工作区虚拟机,因此两个独立的安装几乎不会冲突(172.16/12 也是最不可能与企业局域网或 VPN 冲突的私有范围)。新安装会从这样的子网开始;你可以随时在 偏好设置 › 资源 › 工作区子网 中查看、更改或重新随机生成。客户机的地址分配纯粹是来自 Bromure 自有交换机的 DHCP,因此这完全是宿主机端的处理(无需重建镜像),而远程主机会在其状态中公布所选的子网,让富客户端和隧道自动跟随。
对于两个远程主机仍然共享子网的罕见情况,第一个按字面路由,第二个会被赋予一个 100.64.<n>.0/24 的 CGNAT 空间别名,并进行 1:1 保留宿主机八位组的重映射,从而两者可以同时被访问。
警告: 多宿主机别名路由已实现并经过单元测试,但在多个宿主机之间缝合别名感知的 PAC 和浏览器 MCP 重映射的运行时接线仍待完成。单个远程主机是当今完全受支持的配置。 别名一旦接线,其一个已知局限是:一个被别名化的远程主机内部的开发页面若发出一个绝对字面链接
http://192.168.64.x,可能会错误路由;字面(未别名化)的远程主机不受影响。
将开发服务器暴露到互联网
与上述内容无关,在工作区内运行的单个 HTTP 服务,可以通过每个端口一条的 Cloudflare 快速隧道暴露到公共互联网。打开运行中机器的详情(机器菜单 › 机器详情),在端口卡片下找到该服务,然后点按地球图标(工具提示:公开到互联网(Cloudflare 快速隧道))。Bromure 会为该源运行一个 cloudflared 进程,并给你一个随机的 https://<name>.trycloudflare.com URL——无需 Cloudflare 账户。每个服务一条隧道和一个 URL;暴露或取消暴露其中一个,绝不会影响其他服务。
地球的颜色跟踪状态:灰色 = 关闭,橙色 = 正在安装或启动,绿色 = 运行中,红色 = 失败。端口下方的一条状态行显示进度(正在下载并验证 cloudflared(约 18 MB,一次性)…,然后是正在启动隧道…),或显示可点击的公共主机名以及一个复制按钮。
第一次暴露任何服务时,会出现一个标题为 通过 Cloudflare Tunnel 将服务公开到互联网? 的一次性同意对话框,说明下载、验证、隧道进程(会记录在安全时间线中)、Cloudflare 的服务条款,以及任何拥有该随机 URL 的人都能访问该服务这一事实。再次点按地球图标即可停止。
cloudflared 二进制文件是固定的版本,在运行之前会经过两次验证:下载归档的 SHA-256 会与内置于应用中的哈希值比对,而 Developer ID 代码签名检查会确认 Cloudflare 的团队 ID。它以 --no-autoupdate 运行。
警告: 快速隧道 URL 对任何持有它们的人都是公开的,并且每当隧道重启时(重启、取消暴露/重新暴露或崩溃),主机名都会轮换。只有 HTTP(S) 源才会获得地球——SSH 以及众所周知的原始 TCP 或数据库端口(22、1433、3306、3389、5432、5672、5900、6379、9092、11211、27017)和 UDP 永远不会,因为浏览器无法通过 Cloudflare 的边缘访问它们。当一个工作区的虚拟机挂起或关闭时,它的所有隧道都会被拆除。下载时的哈希不匹配会拒绝安装,直到在某个应用版本中更新该固定值。
OAuth 回调转发
运行在工作区虚拟机内部的 CLI——gh、gcloud、一次订阅登录——通常会通过在你的宿主机 Mac 上打开浏览器并等待重定向到 http://127.0.0.1:<port>/callback 来完成 OAuth 流程。Bromure 会自动桥接:宿主机在 IPv4 和 IPv6 上都绑定该环回端口,并在第一个真实请求到来时通过 vsock 5010 将其拼接到客户机自己的 127.0.0.1:<port>。redirect_uri 从不会被重写,因此 PKCE 和重定向验证仍然通过。无需配置任何东西——在工作区内部启动登录,重定向就会被送达客户机。
该转发器会在 300 秒后自行拆除,因此环回端口绝不会被无限期占用。如果宿主机端口已被占用,流程会在没有桥接的情况下原生进行,而推测性的浏览器预连接(打开但从不发送数据的套接字)会被忽略,从而它们无法卡住一个单次回调服务器。
安全模型
远程访问功能强大,因此值得精确说明它的边界。
- 默认关闭,唯一一扇门。 在你启用 SSH 服务器之前,不存在任何远程路径。每一条路径——人类菜单、CLI、富客户端、端口转发、浏览器 MCP——都经由那唯一一台服务器,别无其他。
- 加密与传输。 所有流量都是 SSH。富客户端的状态流和控制调用、终端附加、文件传输、端口转发和浏览器 MCP 中继,全都在 SSH 连接内传输。由于 swift-nio-ssh 没有后量子密钥交换,新版 OpenSSH 客户端会显示“not using a post-quantum key exchange”警告;这是预期中的情况,并不表示遭到降级攻击。
- bromure.io 是引荐方,而非中间人。 在账户路径中,bromure.io 只引荐你的两台设备,并在无法建立任何直接点对点路径时,通过一个 TURN 中继(基于 TLS)转发不透明的字节。它从不终止 SSH 会话:加密隧道在你的两台 Mac 之间端到端运行。SSH 密钥只在你自己账户的设备之间共享(绝不与其他用户共享),每台服务器自行拉取其所有者的设备密钥,而注册/登出正是授予和撤销某台设备信任的方式。已登出或闲置 90 天的设备会停止被授权。
- 谁可以登录。 只有启动应用的那个确切的 macOS 用户。密码认证根据 OpenDirectory 验证(无远程登录、无 PAM 更改、无管理员权限),公钥认证只接受你已注册的密钥。密码尝试按来源 IP 限速;密钥则不限速。
- 一次会话能做什么。 一次人类登录只能到达远程菜单——永远不是 shell——因此它可以创建、配置和驾驭工作区,但无法运行任意宿主机命令。富客户端的四条机器动词同样狭窄:一个控制套接字桥、一个到 vmnet 子网上客户机的转发,以及一个浏览器 MCP 中继。对宿主机本身、网关或互联网的转发都会被拒绝。
- 机密绝不离开宿主机。 远程设置的读取会清空机密(模型提供方的密钥会被遮蔽),保存则会保留机密;API 密钥、令牌、订阅登录和 MCP 环境机密都留在远程 Mac 上。
- 首次使用时信任。 富客户端在首次接触时按端点固定远程主机的主机密钥,并在此后的任何更改时大声警告。
- 客户机无法伪造的许可。 运行中的代理引发的 MITM 许可提示在终端泵的宿主机侧渲染,在那里被入侵的客户机既看不到也无法伪造它们;任何超时或分离都解析为拒绝。参见远程许可处理。
故障排除
| 症状 | 可能原因 | 应对方法 |
|---|---|---|
| 启用返回错误 | 基础镜像缺失或仍在安装 | 在基础镜像就位之前,服务器无法启动。完成安装,然后再次启用。 |
ssh 已连接但提示用 ssh -t 重新连接 | 未请求 TTY | 远程菜单需要一个终端;添加 -t(或使用 ssh -t -p 2222 <user>@<mac>)。 |
| OpenSSH 打印 “not using a post-quantum key exchange” | swift-nio-ssh 没有 PQ 密钥交换 | 预期之内且无害——连接仍然是加密的。 |
| 按地址连接不停索要密码 | 这台 Mac 的密钥未在远程主机上注册 | 让一次密码登录自动注册它,或在远程主机上运行 bromure-cli remote key add '<this Mac's key>'(显示这台 Mac 的密钥会复制它)。 |
| bromure.io 连接仍索要密码 | 密钥注册表尚未在该服务器上授权此设备 | 这里免密码是自动的——检查你在两台 Mac 上都已登录 bromure.io、服务器已开启远程访问、且两者都在运行当前版本(服务器会发布其登录账户并拉取你的密钥)。启用远程访问后请等待几秒。 |
| 我的服务器 · bromure.io 为空 | 未登录,或服务器未在通告 | 登录(应用名菜单 → 登录到 bromure.io…);在远程主机上启用远程访问,使其发送心跳并出现。灰显的行意味着它已停止发送心跳。 |
| “无法通过 bromure.io 建立连接……” | 两台 Mac 之间没有直接或中继的网络路径 | 确认两者都能到达 bromure.io;中继需要 turns:5349 可达。重试——下次尝试会重试一条路径。 |
| “已通过 bromure.io 到达……,但其 SSH 前门未应答” | 远程主机上的远程访问被关闭了 | 在远程 Mac 上重新启用远程访问。 |
| “这台 Mac 的 bromure.io 设备已被吊销。请重新登录。” | 此设备已被登出/吊销(由你、Web 控制台,或闲置 90 天) | 重新注册:应用名菜单 → 登录到 bromure.io…。 |
| 红色的信任新密钥并继续面板 | 远程主机的主机密钥自固定以来已更改 | 带外核实;只有在你知道密钥为何更改(重装、新 Mac)时才继续——否则它可能是中间人攻击。 |
| 编辑密钥后正在进行的连接中断 | 添加或移除授权密钥会重启监听器 | 预期之内;重新连接。 |
| 浏览器窗格一直空白 | SOCKS 转发器或子网尚未就绪 | 等待镜像的第一次状态更新;确认机器正在运行,且这台 Mac 已安装浏览器镜像。 |
| 转发被拒绝 | 目标不是远程主机 vmnet 子网上的客户机 | 转发只能到达工作区虚拟机,绝不能到达宿主机、网关或互联网。 |
| 隧道开关卡在正在等待批准… | 特权辅助程序尚未获批 | 在系统设置 → 通用 → 登录项中批准 Bromure Agentic Coding(需要管理员)。没有它,SOCKS 仍然可用。 |
| 网格布局编辑在远程主机上不生效 | 远程主机是无头的 | 网格编辑需要在远程主机上打开一个 GUI 窗口;其他一切仍会镜像。 |
文件、端口与环境变量
服务器端状态位于 ~/Library/Application Support/BromureAC/remote/ 下:hostkey_ed25519(0600)及其 .pub、authorized_keys(0600),以及可选的 overlay-key 覆盖文件。富客户端的身份和状态位于 ~/Library/Application Support/BromureAC/remote-client/ 下:id_ed25519(.pub)(注释 bromure-ac-fatclient)、known_hosts(TOFU 固定信息)、hosts.json(已保存的服务器),以及每个宿主机的镜像持久化数据位于 hosts/<host-UUID>/ 下。整个支持目录会随 CFFIXED_USER_HOME 一起迁移。
| 端口 / 接口 | 角色 |
|---|---|
TCP 2222(可配置,≥ 1024) | 嵌入式 SSH 服务器,默认绑定 0.0.0.0。 |
出站 TCP 443 + turns:5349 | 仅 bromure.io 账户路径。 到达你的账户(设备目录、会合),以及在无法建立任何直接点对点路径时的 TURN 中继(基于 TLS)。对于账户路径,两者都必须能从每台设备到达;与按地址路径无关。 |
| 客户机 vsock 5010 | 每个虚拟机中始终开启的环回中继——端口转发和 OAuth 回调送达的路径。 |
| 客户机 vsock 5830 | 工作区代理的浏览器 MCP 流,中继到富客户端的浏览器窗格。 |
临时端口,绑定 0.0.0.0 | 每个宿主机的 SOCKS5 转发器(对等端过滤为环回和 192.168.127.x 浏览器子网)。 |
192.168.127.0/24 | 富客户端固定的本地浏览器虚拟机子网。 |
100.64.<n>.0/24 | 在设备群子网冲突时分配的 CGNAT 别名子网。 |
相关的 UserDefaults 键(域 io.bromure.agentic-coding)为 remoteAccess.enabled、remoteAccess.port、remoteAccess.bindAddress、remoteAccess.passwordAuth、remoteAccess.pubkeyAuth、fatclient.tunnel.<host-UUID> 和 cloudflareTunnel.consented。诊断用环境变量包括 BROMURE_OVERLAY_KEY(远程菜单快捷键)、BROMURE_FATCLIENT_LOG(富客户端的详细日志)和 BROMURE_FATCLIENT_UTUN(强制启用系统级隧道的可选功能——工具栏开关才是产品路径)。完整的 CLI 参考,包括隐藏的 __forward、__forward-socks、__dial 和 __attach-window 底层命令,位于 CLI、API 与 MCP。