沙盒策略
沙盒策略窗格(位于安全组,在防护栏与供应链之间)决定一台机器的 VM 可以连到哪里,而在 OpenShell 引擎下,还决定它的代理在 VM 里可以做什么(机器在设置编辑器中即工作区)。5.4 之前它叫做防火墙;在设置中搜索 firewall、openshell、sentry 或 landlock 仍然找得到它。
窗格一打开只有一个选择,Sandbox engine(沙盒引擎):
| 引擎 | 它是什么 |
|---|---|
| Bromure Firewall | “依主机、地址、协议与端口来允许或拒绝 VM 的连接。”一张有顺序的允许/拒绝规则表,在 Mac 上执行。新机器的默认。 |
| OpenShell + Sentry | “在 VM 中执行、由内核哨兵监看的 NVIDIA OpenShell 策略。”一份 YAML 策略(默认全部拒绝),再加上客户机沙盒与内核哨兵。 |
引擎如何运作,以及它们如何与 Bromure 的其他防护搭配,请参阅沙盒策略、客户机沙盒与内核哨兵。本页是字段参考。
切换到 OpenShell + Sentry 时,会把你组织的默认策略(或 Bromure 的初始策略)填入空白的策略,并以 Best effort 开启内核哨兵。在已有策略的情况下切回 Bromure Firewall,会先询问 Switch to the Bromure Firewall?,因为 Discard OpenShell policy 会移除策略并关闭内核哨兵(除非你的组织要求开启)。若想保留策略,请先用 导出…。
两种引擎都适用的防护——策略拦截时告知代理、代理看门狗、严格凭据、透明拦截与不安全绕道——都在护栏 › 防护。
Bromure 防火墙
出站规则
“依主机、IP/CIDR、协议与端口来允许或拒绝 VM 的连接——自上而下比对,第一个命中者说话。”规则涵盖任何协议与任何目的地。未匹配流量决定没有任何规则命中的连接会怎样:允许(默认),或在采白名单做法时选拒绝。添加规则会附加一行。
| 列 | 值 | 意义 |
|---|---|---|
| (复选框) | 开 / 关 | 取消勾选一条规则即可关闭它而不删除。关闭的规则会保留、变暗,并在你再次勾选前被忽略。 |
| 动作 | allow / deny | 命中时会怎样。 |
| 协议 | tcp / udp / web / any | web 是 HTTP(S),也是唯一其规则还能限制方法的协议。 |
| 主机 / CIDR | any、一个主机名称,或一段 IPv4 CIDR | example.com 涵盖该域名与所有子域名;*.example.com 只涵盖子域名。单独一个 IP 就是 /32。 |
| 端口 | any、一个端口、一段范围(8000-8999)或一份清单 | 留空表示任意。 |
| 方法 | HTTP 动词,只有 web 规则有 | 搭 allow 时只有这些动词通得过(GET,POST);搭 deny 时这些动词会被拒(PUT,DELETE)。read-only 意指 GET/HEAD/OPTIONS。 |
| 时限 | 时钟菜单 | 让规则在有限时间内开启:开启 15 分钟、开启 1 小时或开启直到工作区停止;设为永久会移除时限。有时限的规则会显示剩余时间(“14m”),直到停止的规则会显示“until stop”。 |
“规则在你编辑的当下就生效;取消会把它们还原。”不需要重启,也不需要存储:新的连接立刻遵循新规则,已打开的连接也一样。关闭一条规则、移除它、添加一条拒绝规则、时限到期,或直到停止的规则结束,都会重新检查这台机器所有已打开的连接,而新规则拒绝的连接会在两端都被切断。关闭一个临时的允许就真的结束了访问,而不是让一个已打开的下载跑完。
- 经由代理设置(
HTTPS_PROXY——curl、git、npm 和代理默认都会使用)建立的连接由代理本身切断:它关闭 VM 那一端,并取消发往服务器的请求,WebSocket 也包括在内。安全时间线会把每一条记录为 连接已关闭——“allow tcp …”不再允许它。 - 直接连接由虚拟交换机在下一个数据包时切断:它丢弃该数据包并向 VM 发送一个 TCP 重置,而对于被拦截的 HTTP(S) 流量,代理通往服务器的连接也会被关闭。
如果在编辑器开着时,规则在编辑器之外被更改——安全时间线上的一个操作,或时限到期——这项更改会合并进你尚未存储的编辑。如果你也编辑了同样的规则,窗格会询问:重新载入或保留我的编辑。
临时规则
有些规则只需要一会儿——例如连上 GitHub 或 npm registry,只为了升级依赖。与其添加规则再记得删掉它,不如用规则的时钟菜单设置时限:
- 开启 15 分钟 / 开启 1 小时——时间一到,规则就不再命中,即使 Bromure 正忙也一样;不久之后它会被关闭并以这个状态存储,所以会留在列表中供下次使用。
- 开启直到工作区停止——机器停止(或重启)时规则会被关闭;如果应用退出时它仍在运行,则在下次启动 Bromure 时关闭。
之后要再用这条规则,勾选它或选一个新的时限即可。
要允许刚被拦截的东西,最快的方法是机器窗口里的 Sandbox 抽屉,或安全时间线中被拦截那一行上的允许…。两者都提供始终、15 分钟、1 小时与直到工作区停止。
pf 格式
pf 格式展开区把同一组规则以文字呈现——一行一条,最后以 default allow 或 default deny 结尾——这正是它们被保存的样子,也是 CLI 与受管描述文件所使用的形式:
allow tcp api.github.com:443
allow web api.example.com GET,POST # 只有这些动词到得了那个网站
deny web api.internal PUT,DELETE # 挡下这些动词,其余放行
deny udp any:53
deny any 10.0.0.0/8
default deny
关闭的和临时的规则会在注释中带一个简短标记,让文本仍是纯粹的 pf:
#@off allow tcp registry.npmjs.org:443 # 已关闭
allow tcp github.com:443 #@until=1767225600 # 开启直到此时间(Unix 秒)
allow tcp pypi.org:443 #@until=stop # 开启直到机器停止
执行发生在 Mac 上,分两层:虚拟网络交换机依目的地 IP 与在 DNS 中看到的主机名称检查每一条连接(所有协议),而代理服务器再依 TLS 服务器名称、以及对 web 规则再依 HTTP 方法检查一次。这正是一台机器能读取它不能写入的 API 的原因:allow web api.example.com GET,POST 给代理的是没有更改的查询,不论它用什么工具。
每一项判定都会连同做出判定的规则记录在安全时间线中,并在已注册的 Mac 上发送给你的组织。
记录允许的连接
被阻止的连接总会记录。位于未匹配流量选项之下的记录允许的连接,决定防火墙放行的连接是否也要记录——正是它让这些行有**阻止…和规则…**快捷操作。在你做出选择之前,机器有规则(或拒绝未匹配流量)时它是开启的,没有防火墙的机器则是关闭的,所以没有规则的机器不会让时间线塞满“允许”的行。
无论如何,允许的连接都保持低噪音:每个目标(主机、端口和协议——位于多个地址后的主机算一行)最多每分钟一行,重复的会以计数折叠进前一行。Mac 上本地模型的端点永远不会列出。
注意: 本地模型永远是可达的:对 Mac 上推理端点的允许规则会被放在你的规则之前,所以就算
default deny也切不断代理与设备端模型的联系。
防火墙下的内核哨兵
内核哨兵属于 OpenShell 引擎。仍在 Bromure 防火墙下运行它的机器,会显示一张附 Turn off 的 Kernel sentry is still on 卡片;若你的组织要求哨兵,则显示“Your organization requires at least …”,且没有任何控件。
OpenShell + Sentry
这个引擎的设置分成五张卡片。
策略
“除非有规则允许,否则一律拒绝。实时生效。”Policy 卡片放的是策略本身:一份以 YAML 编写、架构版本 1 的 NVIDIA OpenShell 沙盒策略。只有 network_policies 规则能允许连接;带有 protocol 的端点会逐个请求检查,enforce 会拦截,audit 只记录。更改无需重启就会应用到运行中的机器。
卡片上的按钮:
- 导入…——以一个
.yaml/.yml文件替换策略。 - 导出…——将它存成
<machine>-policy.yaml。 - Reset to starter policy——初始策略允许 GitHub(443 端口上的
github.com、api.github.com、**.githubusercontent.com)、只读的 npm 与 PyPI(经检查,enforce),以及 80/443 端口上的 Ubuntu 软件包镜像站。
编辑器下方有一行检查结果,显示 Valid policy · N network rules(绿色)或解析错误(红色),之后列出任何警告。开启 Enforce binaries 时,没有列出任何 binaries 的规则会以橙色标出:它们什么也不允许。
内核哨兵
“把安全事件(进程启动、权限变更、模块与 BPF 加载、沙盒拒绝)从 VM 的内核串流给 Bromure,不经过任何代理能停掉的东西;启动之后,内核会被锁定,连 VM 中的 root 都无法加载代码来干扰。”串流中的静默或缺口,对代理看门狗而言都算篡改。
| 模式 | 行为 |
|---|---|
| Best effort | 模块能加载时机器就带着哨兵运行,否则不带哨兵。切换到 OpenShell 时会选这个。 |
| Required | 在哨兵就位之前(已加载,或已报告为何无法加载),VM 中什么都不会运行。内核会被进一步锁定(因此也排除了 bpftrace 与 perf 这类内核追踪工具),而始终没有连上、也没说明原因的哨兵会被视为篡改。 |
Mode 在下次 VM 启动时生效。当你的组织设了最低要求时,以两者中较严格的为准,而在最低要求为 Required 时,Best effort 会呈灰色(“Your organization requires it.”)。在哨兵随引擎提供之前就配置好的机器,会显示 Off for this workspace 并附 Turn on。
卡片的状态行会显示 Connected · kernel 版本 或 Not connected、负载下丢失了多少事件(若有),以及当 VM 无法加载哨兵时以红色显示的 Couldn't start: 原因。哨兵的模块如何送达,请参阅内核哨兵。
沙盒
当 VM 报告问题时,卡片标题会变成橙色的 Sandbox ⚠︎:文件系统沙盒或严格沙盒没有应用、预期应有的哨兵无法使用,或客户机发来了警告。
| 设置 | 默认 | 作用 |
|---|---|---|
| Enforce binaries | 关闭 | “规则只适用于它们列出的程序;代理会失去 sudo 与 Docker。”VM 中一个属于 root 的证明程序会报告每条连接背后的程序,而规则的 binaries 必须点名它。每个程序的哈希值在首次使用时固定下来,被改动过的二进制文件会被拒绝。代理没有任何通往 root 的路:没有 sudo、没有 Docker,所有流量都经过透明拦截。下次 VM 启动时生效。当你的组织或策略的 process 分区要求时,会被锁定为开启。 |
| Filesystem & process | 依策略 | “代理只能访问策略列出的路径。”依策略的 filesystem_policy 与 process 分区,在 VM 中以 Landlock 执行;连 root 都无法解除。两个分区都没有时,这一行会显示“Not confined”并提供 Insert template,它会附加一份典型的 filesystem_policy(系统文件夹只读,主目录与 /tmp 可读写)。下次 VM 启动时生效。 |
| Packages in the home folder | 开启 | “pip 安装到 ~/.local;npm 本来就用 ~/.npm-global。”沙盒没有 root,所以全系统的安装行不通。在新的终端中生效。 |
| System packages on request | 开启 | “apt-get install 会先问你;代理永远拿不到 root。”请求会在 Sandbox 抽屉中等候;批准后,Bromure 会从 Ubuntu 的镜像站安装正好那些软件包。下次 VM 启动时生效。 |
Enforce binaries 与 Filesystem & process 下方的状态行,说明 VM 实际应用了什么:
- Attestor connected: binaries are enforced,或 Attestor not connected: until it is, only Bromure's own rules apply。
- Filesystem 之后接着它的状态、代理以哪个用户身份运行,以及 Landlock 版本;在 VM 报告之前则是 Filesystem not applied yet。
- Bromure 为自己的管线添加的路径(Added for Bromure: …)。
- 文件系统已受限、但二进制文件未强制时:“The agent keeps sudo, so it could stop Bromure's processes in the VM. Turn on Enforce binaries to prevent that.”
- 严格沙盒没有应用时,以红色显示:“no session will start and binary rules fail closed. Restarting the VM retries it.”
策略顾问
当请求被拦截时,代理可以在 http://policy.local(OpenShell 的顾问 API)提出它需要的那条窄规则,并等待你的决定。被拦截的连接也会在这里被草拟成提案。
| Agent proposals | 行为 |
|---|---|
| Off(默认) | 代理不能提出规则。被拦截的连接仍会被草拟成提案。 |
| Ask me | 每个提案都等你决定。 |
| Approve if risk-free | 没有风险发现的提案会立即批准。连到机器持有凭据的主机、在那里增加方法,或使用通配符、私有地址、数据库或高位端口的提案,一律等你决定。 |
每个待处理的提案会显示它的规则与目的地、它是 drafted from a block(由拦截草拟)还是 proposed by the agent(由代理提出)、代理陈述的意图、YAML,以及以橙色标出的任何风险发现。如果愿意,可以输入 Reason (sent to the agent on reject),再点击 Reject 或 Approve。批准的规则会加入策略并实时生效。Recent decisions 会列出最近五条。同样的提案也会出现在 Sandbox 抽屉中。
治理
- Organization boundary——任何机器的策略所能允许的上限。它可以是 Set by your organization (bromure.io)、Set on this Mac(附 Set from file… 与 清空),或 None set.。每次更改策略的存储都会与它比对:装有 NVIDIA 的
openshell-prover时用它,否则用 Bromure 内置的检查。超出边界的策略,不论是在哪里编辑的——窗格、Sandbox 抽屉、顾问或 API——都会被拒绝,并附上边界的摘要。 - Revision history——每次更改策略的存储都会保留为一个版本(vN,附日期、更改来源与一段短哈希值)。恢复 会把某个版本载回编辑器。
- Rules Bromure adds automatically——如同 OpenShell 的提供方规则,这些规则让机器的代理与它配置的每个凭据都连得到。它们不属于导出的策略。
被拦截时代理看到什么
策略拒绝的连接会立刻失败,不会留下悬着的 socket。在 OpenShell 策略下,被拒绝的代理连接或受检查的请求,会收到带有 OpenShell 自己 policy_denied 正文的 HTTP 403:哪一层、主机与端口(或方法与路径),以及规则或原因。策略顾问开启时,正文也会告诉代理如何在 http://policy.local 提出规则。开启 Tell the agent when policy blocks it(见护栏)时,代理还会在它的对话中被告知它尝试了什么、策略禁止这么做,以及应该来问你而不是绕过去。
设置参考
| 设置 | 类型 | 默认 |
|---|---|---|
| Sandbox engine | Bromure Firewall / OpenShell + Sentry | Bromure Firewall |
| 未匹配流量(防火墙) | 允许 / 拒绝 | 允许 |
| 记录允许的连接(防火墙) | 复选框 | 机器有规则时开启 |
| 规则(防火墙) | 有顺序的表格(添加规则),也以 pf 格式 显示 | 无 |
| 策略(OpenShell) | YAML,架构 v1 | 组织默认,或初始策略 |
| 内核哨兵 Mode | Best effort / Required | OpenShell 下为 Best effort;防火墙下关闭 |
| Enforce binaries | 开关 | 关闭 |
| Packages in the home folder | 开关 | 开启 |
| System packages on request | 开关 | 开启 |
| Agent proposals | Off / Ask me / Approve if risk-free | Off |
| Organization boundary | 文件,或由你的组织设置 | 无 |
规则表格与策略编辑器不会出现在 iPhone、iPad 或 Vision Pro 客户端上(“Outbound connection rules are edited on the Mac that runs this workspace.”);在 Mac 上设的规则与策略仍然生效。
相关章节
- 沙盒策略、客户机沙盒与内核哨兵 — 引擎如何运作。
- 护栏 — 凭据策略,以及两种引擎共用的防护。
- 凭据 — OpenShell 提供方配置文件与凭据占位符。
- 安全概览与时间线 — 每一次封锁与放行,按机器分,以及网络溯源链。