nmicic/compartment
GitHub: nmicic/compartment
内核强制沙箱隔离工具,提供零依赖核心工具和共享配置文件格式。
Stars: 2 | Forks: 0
# 间隔 — Linux进程隔离工具包
为不受信任的进程提供内核强制沙箱隔离。两个零依赖核心工具,一个共享配置文件格式,以及可选的BPF-LSM模块。
## 什么是
| 工具 | 目的 | 根? | 依赖 |
|------|---------|-------|------|
| **compartment-user** | Landlock + seccomp + 环境净化 + 审计 | 否 | 无 |
| **compartment-root** | 完全命名空间容器 + seccomp + 审计 | 是 | 无 |
| **sandbox.sh** | 网络命名空间 + 代理桥接 | 否 | unshare, socat, newuidmap |
| **compartment-bpf** | 可选的BPF LSM节点密封(内核端拒绝,即使root) | 是 (CAP_BPF + CAP_SYS_ADMIN) | clang ≥ 12, libbpf, bpftool, libsodium, BTF, 内核 ≥ 6.6 with `lsm=...,bpf` |
`compartment-user` / `compartment-root` 使用 Landlock + seccomp(用户空间策略)并且是默认的零依赖路径。
`compartment-bpf` 在 BPF LSM 级别密封单个inode — 执法在内核中,即使root也能生存。两种方法互为补充。有关 BPF 工具及其要求,请参阅 `compartment-bpf/HOWTO.md`。
## 快速入门
```
make
./compartment-user -- /bin/sh # sandboxed shell in 2 commands
./compartment-user --dry-run -- /bin/sh # see what would be applied
```
## 构建
```
make # builds the zero-dependency core tools
make test # run core tests (Landlock + seccomp + env + inheritance)
make test-integration # run all tests (includes Claude CLI smoke test)
make hardened # build with randomized shell stash path
```
可选的BPF模块:
```
cd compartment-bpf
make vmlinux.h && make
```
需要Linux内核6.6+,已启用BPF LSM,以及clang、libbpf-dev、bpftool、libsodium-dev和运行内核的BTF。
## 使用
```
# 沙盒化 AI 代理(Landlock + seccomp,无 root)
./compartment-user -- claude --model claude-opus-4-6
# 使用配置文件
./compartment-user --profile strict -- codex --full-auto
# 查看不运行时将应用的内容
./compartment-user --dry-run -- claude
# 完整命名空间容器(需要 root)
./compartment-root --profile examples/container.conf -- /bin/sh
./compartment-root --rootdir /srv/jail -U svc --audit -- /usr/bin/myapp
# 完整隔离(网络命名空间 + 代理 + Landlock + seccomp)
./sandbox.sh claude --model claude-opus-4-6
```
## 示例:强化SSH(网络客户端的权限分离)
间隔可以锁定任何网络客户端——不仅仅是AI代理。
以下是一个使用SSH的工作示例,展示了如何将进程分割成权限分离的组件,以便单个妥协无法同时访问机密信息并将其泄露。
### 问题
如果远程SSH服务器被入侵,它可以逆向利用SSH客户端。被木马化的客户端可以:
- 将被盗凭据写入 `~/.ssh/exfil.txt`
- 将按键记录到隐藏文件
- 通过网络将数据泄露到第三方主机
### 解决方案1:只读SSH (`ssh.conf`)
锁定SSH客户端以只读文件系统访问。它可以读取密钥进行身份验证,但不能将任何内容写入磁盘:
```
# 一行命令:SSH 无文件系统写入
./compartment-user --profile examples/ssh.conf -- ssh user@host
# 如果 SSH 二进制文件尝试写入会发生什么:
# touch /tmp/exfil.txt → EACCES(被 Landlock 阻挡)
# echo x > ~/.ssh/log.txt → EACCES(被 Landlock 阻挡)
# cat ~/.ssh/id_ed25519 → OK(读取允许)
```
### 解决方案2:偏执SSH (`paranoid-ssh.sh`)
将SSH分割成两个具有互补限制的沙箱进程:
```
┌──────────────────────────┐ ┌──────────────────────────┐
│ SSH (read-only fs) │────▶│ socat (no user files) │────▶ remote:PORT
│ • can read keys │ │ • no $HOME access │
│ • cannot write anywhere │ │ • cannot read SSH keys │
│ • Landlock + seccomp │ │ • Landlock + seccomp │
└──────────────────────────┘ └──────────────────────────┘
localhost:RANDOM_PORT
```
```
# 对远程服务器进行偏执 SSH
./examples/paranoid-ssh.sh user@remote-host
# 使用自定义端口
./examples/paranoid-ssh.sh user@remote-host -p 2222
# 运行命令
./examples/paranoid-ssh.sh user@remote-host "uptime"
```
**安全属性:**
- **SSH进程**可以读取 `~/.ssh/` 密钥,但不能写入磁盘
→ 被逆向利用的SSH无法将被盗数据本地保存
- **socat进程**具有网络访问权限,但不能读取任何用户文件
→ 即使socat被利用,攻击者也无法访问凭据
- **任何单个进程**都无法同时访问机密信息并将其泄露
这与OpenSSH自身的权限分离原则相同,但它在操作系统级别使用Landlock + seccomp实现,而不是信任应用程序自行分离。
### 为什么这很重要(2026年范式)
传统的系统管理员思维:“SSH是可信的,网络是不可信的。”
间隔思维:“没有任何东西是完全可信的。将每个进程分割,以便任何单个组件的妥协都无法同时实现数据访问和数据泄露。”
这种模式适用于任何网络客户端:
- **curl/wget** — 只读配置文件防止保存下载的恶意软件
- **git** — fetch的只读配置文件,workdir的写入配置文件
- **数据库客户端** — 防止凭据记录到磁盘
- **AI代理** — 主要用例(请参阅 `sandbox.sh`)
## 工作原理
**compartment-user** 在exec之前应用内核强制限制:
1. `PR_SET_NO_NEW_PRIVS` — 防止权限提升
2. **Landlock** — 文件系统路径限制(只读系统路径,可写工作目录)
3. **seccomp BPF** — 阻止危险的系统调用(ptrace、mount、kexec、bpf、io_uring、...)
4. **环境净化** — 移除 LD_PRELOAD、LD_LIBRARY_PATH、等
5. **审计日志** — 每日文件日志,带有PPID链
所有限制都会由子进程继承,并且无法删除。
**compartment-root** 创建一个完全隔离的容器:
1. `clone()` 与新的 UTS、mount、PID、IPC、net、user命名空间
2. **pivot_root** — 旧的root完全卸载(比chroot更强)
3. 最小 `/dev`、隐藏 `/proc`、隔离主机名
4. **能力下降** — 原始prctl + capset,无libcap。`cap-allow` 通过 `PR_SET_KEEPCAPS` + `capset()` 保留服务用户命名的权限
5. **seccomp BPF** — 原始BPF,无libseccomp
6. **环境净化** + **审计日志**(与 compartment-user 相同)
**sandbox.sh** 将命令包装在用户+mount命名空间中:
1. `unshare --user --mount --net` — 硬件模式:仅回环(无外部接口);
软 fallback:slirp4netns with `--disable-host-loopback`
2. Unix套接字代理桥接 — API流量通过公司代理路由
3. 绑定挂载shell替换 — 每个 `/bin/bash` 子进程都得到沙箱隔离
(需要挂载命名空间,sandbox.sh 创建)
在硬件模式下,如果已配置代理,则命名空间没有外部接口——网络流量仅通过Unix套接字代理桥接。(自动测试验证代理可达性,但尚未包括直接绕过抵抗测试。)
## 配置文件
两个工具共享相同的 `.conf` 格式:
```
# 文件系统(compartment-user:Landlock)
ro /usr
rw $HOME
# 文件系统(compartment-root:namespaces)
rootdir /srv/containers/default
uid 1000
gid 1000
username svc
loopback on
# 系统调用
block ptrace
block mount
# 或允许列表模式:
# 允许读取
# 允许写入
# 环境
env-deny LD_PRELOAD
# 功能
seccomp on
no-new-privs on
env-sanitize on
audit on
```
搜索顺序:`--profile /path/file.conf` → `~/.config/compartment/.conf` → `/etc/compartment/.conf` → 内置。
有关完整格式参考,请参阅 [HOWTO.md](HOWTO.md).
## 示例
每个配置文件针对不同的威胁模型。选择与您要保护的内容相匹配的配置文件。
| 文件 | 使用时 | 保护 |
|------|----------|------------------|
| `ai-agent.conf` | 运行Claude、Codex、Gemini CLI | 代理在工作目录外读取/写入,启动意外的进程 |
| `strict.conf` | 不受信任的代码,比ai-agent更严格 | 与上述相同,系统调用表面积更小 |
| `ssh.conf` | 在您不完全信任的机器上运行SSH客户端 | 被入侵的SSH二进制将凭据写入磁盘 |
| `socat-proxy.conf` | 由 `paranoid-ssh.sh` 内部使用 | socat具有访问您的SSH密钥的权限 |
| `container.conf` | 通过 compartment-root 实现完全命名空间隔离 | 进程逃逸其根目录 |
| `dev.conf` | 开发和调试 | 没有东西——这是故意放宽的 |
**我应该使用哪一个?**
- **沙箱化AI代理** → `ai-agent.conf`(默认)或 `strict.conf`(更严格)
- **连接到远程服务器** → `paranoid-ssh.sh`,它结合了 `ssh.conf` + `socat-proxy.conf`。SSH进程可以读取您的密钥,但不能写入任何地方。socat进程处理网络连接,但不能读取您的密钥。任何单个进程都无法同时窃取凭据和泄露它们。
- **运行不受信任的服务** → 使用 `compartment-root` 的 `container.conf`
- **找出为什么某些内容被阻止** → `dev.conf`,然后从那里开始收紧
## 对任何程序进行配置文件生成
不要手动编写配置文件。使用 `tools/syscall.py` 为任何程序自动生成一个:
```
# 步骤 1:检查——默认配置文件是否会破坏您的程序?
python3 tools/syscall.py check --profile ai-agent -- wget -q -O /dev/null https://example.com
# 步骤 2:如果破坏了,生成自定义配置文件
python3 tools/syscall.py profile -o examples/wget.conf -- wget -q -O /dev/null https://example.com
# 步骤 3:使用它
./compartment-user --profile examples/wget.conf -- wget https://example.com
```
适用于任何东西:`curl`、`git`、`ssh`、`rsync`、`python3`、数据库客户端——您可以运行的任何程序,您都可以对其进行配置文件生成和沙箱化。
```
# 更多示例
python3 tools/syscall.py profile -o curl.conf -- curl -s https://example.com
python3 tools/syscall.py profile -o git.conf -- git clone https://github.com/user/repo
python3 tools/syscall.py profile -o psql.conf -- psql -c "SELECT 1"
# 严格的允许列表(仅允许观察到的系统调用,拒绝其他所有内容)
python3 tools/syscall.py profile --seccomp-mode allow -o strict-curl.conf -- curl https://example.com
# 查看程序实际使用的系统调用
python3 tools/syscall.py trace -- ssh user@host "echo hello"
```
需要 `strace` (`apt install strace`)。有关完整指南,请参阅 [tools/HOWTO-syscall-profiling.md](tools/HOWTO-syscall-profiling.md).
## Shell替换
compartment-user可以透明地拦截 `/bin/bash`,因此AI代理生成的每个子进程都会得到沙箱隔离:
```
/bin/bash (bind mount) → compartment-user
→ Landlock + seccomp applied
→ exec /bin/shells/bash (the real shell)
```
当 compartment-user 编译并可用时,这将在 `sandbox.sh` 内自动发生。有关手动设置选项,请参阅 [HOWTO.md](HOWTO.md).
## 高级部署:间隔登录Shell
间隔可以作为非管理员用户的登录Shell部署,以便每个交互式会话和每个 `execve("/bin/sh", ...)`
——包括远程利用有效载荷——都会自动进入沙箱Shell。
这是一个针对受控环境的意见设置(加固服务器、跳板、CI运行器),而不是普遍的建议。
### 设置
```
# 使用随机的 shell 储存路径构建
make hardened
# 输出:REAL_SHELL_DIR=/bin/.shells_a1b2c3d4e5f6
# 在储存目录中保留真实 shell
sudo mkdir -p /bin/.shells_a1b2c3d4e5f6
sudo mv /bin/bash /bin/.shells_a1b2c3d4e5f6/bash
sudo mv /bin/sh /bin/.shells_a1b2c3d4e5f6/sh
# 将 compartment-user 安装为系统 shell
sudo cp compartment-user /bin/bash
sudo ln -sf /bin/bash /bin/sh
# 为指定的管理员账户保留正常 shell
sudo chsh -s /bin/.shells_a1b2c3d4e5f6/bash root
sudo chsh -s /bin/.shells_a1b2c3d4e5f6/bash your-admin-user
```
当以 `bash` 或 `sh`(通过 `argv[0]` 检测)调用时,
compartment-user 应用 `ai-agent` 配置文件并从隐藏目录执行真实Shell。
### 权限模型
```
root / admin → /bin/.shells_.../bash (real shell, no sandbox)
all others → /bin/bash (compartment → sandboxed shell)
Landlock + seccomp + env sanitize + audit
```
### 这阻止了什么
调用 `execve("/bin/sh", ...")` 的远程利用有效载荷会得到间隔,而不是bash。有效载荷在执行单个攻击者控制的指令之前会命中Landlock文件系统限制和seccomp系统调用过滤。
沙箱Shell不能 `ptrace`,不能加载内核模块,不能挂载文件系统,并且只写入允许的路径。
### 注意事项
- **兼容性**:一些工作流程期望不受限制的交互式Shell,可能会中断。在部署到生产环境之前彻底测试。
- **不是替代品**:对于正确的主机加固、打补丁和权限分离,这不是替代品。这是一个深度防御层。
- **绕过路径存在**:可以写入ELF二进制到可执行路径并直接调用(而不是通过 `/bin/sh`)的攻击者将绕过shell替换层。父进程上的Landlock限制了它们可以写入的位置,但这不是完全密封的。
- **恢复**:始终保留至少一个具有真实Shell的管理员账户。如果 compartment-user 有漏洞,您需要一种方法返回。
## 要求
- Linux >= 5.13(Landlock)— compartment-user
- Linux >= 4.6(cgroup命名空间)— compartment-root
- Linux >= 3.8(用户命名空间)— sandbox.sh
- 无外部库。compartment-user 无需root权限。
## 文件
```
compartment.h — shared code: profiles, audit, seccomp BPF, env sanitize
compartment-user.c — Landlock + seccomp + audit (zero deps, rootless)
compartment-root.c — Full namespace container (zero deps, requires root)
sandbox.sh — Network namespace + proxy bridge
Makefile — Build targets
HOWTO.md — Detailed setup guide
DESIGN.md — Architecture, security review, lineage from shell-guard
SECURITY.md — Vulnerability reporting policy
examples/
ai-agent.conf — Profile for Claude/Codex/Gemini
strict.conf — Locked-down profile (inherits ai-agent)
container.conf — Full namespace isolation profile
dev.conf — Relaxed profile for development
ssh.conf — Read-only SSH client (no filesystem writes)
socat-proxy.conf — Network-only socat bridge (no user file access)
paranoid-ssh.sh — Privilege-separated SSH (SSH+socat split)
tools/
syscall.py — Profile generator: trace any program, emit .conf
HOWTO-syscall-profiling.md — Full guide to syscall profiling
man/
compartment-user.1 — Man page (section 1: user commands)
compartment-root.8 — Man page (section 8: system administration)
tests/
probes/deny_probe.c — Sandbox validation probe (machine-parseable output)
profiles/ — Test-specific .conf profiles
scripts/run_all.sh — Top-level test runner (52 tests across 4 suites)
README.md — Test documentation
archive/
shell-guard/ — Archived shell-replacement tool (~2003, self-contained)
```
## 与替代方案的比较
```
root required?
no yes
┌───────────────┬───────────────┐
filesystem │ compartment- │ compartment- │
restriction │ user │ root │
mechanism │ (Landlock) │ (pivot_root) │
│ │ │
│ Firejail │ bwrap (setuid)│
│ bwrap (userns)│ Docker/Podman │
├───────────────┼───────────────┤
no filesystem │ seccomp-only │ AppArmor │
restriction │ wrappers │ SELinux │
└───────────────┴───────────────┘
```
- **Firejail** (~100K行) — 最接近的比较;桌面应用程序成熟的配置文件生态系统,但攻击面大,有CVE历史。compartment-user 小100倍,可以一次性审计。
- **bwrap** (~3K行) — mount/PID/网络命名空间。架构不同(命名空间与Landlock)。需要完整挂载隔离或内核 < 5.13 时使用bwrap;需要配置文件、shell替换或在工作区中禁用用户命名空间的容器中使用 compartment-user。
- **Minijail**(Google)—— 表达式seccomp参数过滤,但需要libminijail。compartment-user 以零依赖部署为代价进行参数过滤。
- **AppArmor/SELinux** —— 系统范围的MAC,更细粒度,但需要管理员访问和系统策略安装。compartment-user 是用户可部署的,无需系统配置更改。
没有现有的工具结合:零依赖、具有继承的配置文件、shell替换模式、以及约1600行中的PPID链审计日志。
## 相关
- [bubblewrap](https://github.com/containers/bubblewrap) —— 基于命名空间的沙箱隔离(互补)
- [firejail](https://github.com/netblue30/firejail) —— 命名空间 + seccomp(setuid,配置文件)
## 开发
该项目是在AI辅助下开发的:
- **[Claude Code](https://claude.ai/code)**(Anthropic)—— 主要编码、测试、调试和实现所有C源代码、shell脚本、配置文件和测试基础设施
- **ChatGPT**(OpenAI)、**Gemini**(Google)、**Codex**(OpenAI)—— 独立代码审查轮次,确定了18个安全漏洞,所有漏洞都在发布前得到修复
- **Human** —— 架构、设计决策、审查协调和最终批准
## 许可证
Apache-2.0。请参阅 [LICENSE](LICENSE).
标签:应用安全