跨平台原生沙箱库 —— 在隔离环境中运行不受信任的命令。一套 API,三个平台,每个平台使用操作系统原生的隔离原语。
| 平台 | 隔离引擎 | 需要 root | 备注 |
|---|---|---|---|
Linux (ch) |
Cloud Hypervisor 微型虚拟机 (KVM) + virtiofsd + smoltcp 用户态网络栈 | 不需要(用户需在 kvm 组中) |
当 /dev/kvm + /dev/vhost-vsock + cloud-hypervisor 二进制可用时优先选择 |
Linux (bwrap) |
bubblewrap(用户命名空间)+ smoltcp 用户态网络栈 | 不需要 | CH 不可用时自动回退;~50 ms 启动,无虚拟机 |
| macOS | Apple Virtualization.framework → Linux 微型虚拟机 + smoltcp 用户态网络栈 | 不需要 | ~2 s 冷启动 |
| Windows | Hyper-V HCS → Linux 微型虚拟机 + smoltcp 用户态网络栈(SYSTEM 服务) | 一次性服务安装 | ~600 ms |
所有后端提供完全相同的 Sandbox 接口:configure → create → start → spawn shells → stop。同一个 init 二进制(tokimo-sandbox-init)在每个沙箱中以 PID 1(bwrap 中为 PID 2)运行,使用相同的线路协议,不区分传输层。网络完全统一:所有后端的 AllowAll 策略均使用同一套 smoltcp 用户态网络栈。
Linux 后端选择(SANDBOX_BACKEND 环境变量):
| 取值 | 行为 |
|---|---|
(未设)/ auto |
先探测 ch;不可用时优雅地回退到 bwrap。 |
ch |
强制使用 Cloud Hypervisor;不可用直接报错(不回退)。 |
bwrap |
强制使用 bubblewrap;不可用报错。 |
disabled |
拒绝构造任何后端。 |
Sandbox::active_backend() 返回运行时实际选中的具体后端,便于调用方 / CI 日志确认走的是哪条路径。
现有的沙箱方案要么是平台专属的(bwrap、jail、WSL),要么需要守护进程和镜像(Docker、Podman)。没有一个开源库能让你用一套 Rust API 在 Linux、macOS 和 Windows 上沙箱化一条命令——还要有可用的网络、PTY 支持和动态宿主↔客机文件共享——而不需要 root、Docker 或预构建的容器镜像。
这个项目填补了这个空白。
┌─────────────────────────────────────────────────────────────┐
│ 你的应用程序 │
│ │
│ let sb = Sandbox::connect().unwrap(); │
│ sb.configure(params).unwrap(); │
│ sb.start_vm().unwrap(); │
│ let shell = sb.shell_id().unwrap(); │
│ sb.write_stdin(&shell, b"uname -a\n").unwrap(); │
│ sb.stop_vm().unwrap(); │
└────────────────────────┬────────────────────────────────────┘
│ 各平台完全相同的 API
┌────────────────┼─────────────────────┬────────────────┐
▼ ▼ ▼
LinuxBackend ── Auto:ch → bwrap MacosBackend WindowsBackend
(进程内;connect() 时决定) (进程内) (命名管道 RPC)
│ │ │
├── ChBackend ── cloud-hypervisor ▼ ▼
│ (KVM 微型虚拟机、virtiofsd、 arcbox-vz → tokimo-sandbox-svc
│ hybrid-vsock UDS) VZVirtualMachine (SYSTEM 服务)
│ │ │
└── BwrapBackend │ │
(bubblewrap 用户命名空间) │ │
│ │ ▼
│ │ Hyper-V HCS
└────────────┬────────────────┘ │
▼ ▼
tokimo-sandbox-init Linux 微型虚拟机
(PID 1,共享二进制) (HvSocket 传输)
│
▼
Linux 客机
Linux 平台层会在 Sandbox::connect() 时探测 Cloud Hypervisor,并选择当前主机上能用且最强的后端。CH 优先(真实 KVM 隔离、完整内核边界、与 macOS/Windows 等价的安全姿态);bwrap 是回退(无虚拟机、启动最快、能在没有 /dev/kvm 的环境下工作,例如未开启虚拟化的嵌套 CI)。
两个后端除了隔离原语之外完全共享:同一个 tokimo-sandbox-init PID 1 二进制、同一套 FuseHost/tokimo-sandbox-fuse FUSE 基础设施、同一个 smoltcp 网络栈、同一份协议帧。仅传输层接线不同(SEQPACKET socketpair vs. hybrid-vsock UDS sidecar)。
Sandbox::start_vm()
│
├─ probe_ch() ✅ (/dev/kvm + /dev/vhost-vsock + cloud-hypervisor + virtiofsd)
│
├─ 启动 cloud-hypervisor 子进程:
│ --kernel vmlinuz ← 与 crate 版本配对发布
│ --initramfs initrd.img
│ --cmdline "... tokimo.guest_listens=0 tokimo.init_port=2222 ..."
│ --memory size=<MB> ← 来自 ConfigureParams
│ --cpus boot=<N>
│ --vsock cid=3,socket=<vsock_uds> ← hybrid-vsock;每端口一个 UDS sidecar
│ --fs tag=<mount_name>,socket=<virtiofsd.sock> ← 每个共享一份
│ [--net tap=...] ← 仅 AllowAll
│
├─ 启动 virtiofsd 子进程(每个 ConfigureParams.mount 一个):
│ --shared-dir <host_path>
│ --socket-path <virtiofsd.sock>
│ [--readonly] [--sandbox=none|chroot]
│
└─ 宿主侧 hybrid-vsock UDS sidecar (`<vsock_uds>_<port>`) 上的监听器:
port 2222 → init 控制通道
port 4444 → smoltcp 网络栈 RX/TX
port 5555 → FuseHost(进程内 FUSE-over-vsock)
- 无守护进程、无服务、不需要 root。 每个
Sandbox拥有独立的cloud-hypervisor+virtiofsd进程组。 - 与 macOS/Windows 同一套打包内核 + initrd + rootfs(
vm-kernel-*+vm-rootfs-*tag artifact)。 - vsock 传输 使用 CH 的 hybrid-vsock —— 宿主以监听每端口 UDS(
<vsock_uds>_<port>)的方式扮演 vsock,而不是用/dev/vhost-vsock。四个通道(init、网络栈、FUSE、控制台)全部由客机发起(tokimo.guest_listens=0)。 - 文件共享 ConfigureParams 中声明的挂载使用
virtiofsd(CH 的天然原语),不走 FUSE-over-vsock。运行时add_mount仍然通过同一份FuseHost走 FUSE-over-vsock。 - 网络:
AllowAll与其他后端使用同一套 smoltcp 用户态网络栈。Blocked直接省略网卡。 - PTY: 主 fd 留在客机;init 通过协议事件(vsock)桥接 I/O。
Sandbox::start_vm()
│
├─ socketpair(AF_UNIX, SOCK_SEQPACKET) ← init 控制通道
├─ socketpair(AF_UNIX, SOCK_STREAM) ← 网络栈(仅 AllowAll)
│
└─ exec bwrap --unshare-user --unshare-pid --unshare-ipc --unshare-uts
--unshare-net ← 始终:全新网络命名空间
--ro-bind <.vm/base/rootfs>/{usr,bin,sbin,lib,lib64}
--ro-bind <.vm/base/rootfs>/etc/{passwd,group} ← 打包的用户表
--ro-bind /etc/{resolv.conf,hosts,ssl,...} ← 仅宿主网络/CA
--cap-add CAP_SYS_ADMIN ← fusermount3 需要
--cap-add CAP_NET_ADMIN ← 用于 TAP 和 lo 启动
--cap-add CAP_NET_RAW ← 客机 ping 需要
--cap-add CAP_MKNOD ← 回退 TUN 节点创建
--dev-bind-try /dev/net/tun ← 仅 AllowAll
-- /path/to/tokimo-sandbox-init bwrap
--control-fd=<ctrl>
--net-fd=<net> ← 仅 AllowAll
--bringup-lo --mount-sysfs
│
└─ bwrap 内 PID 2(bwrap 是 PID 1)
├─ 控制:SEQPACKET,PTY 通过 SCM_RIGHTS 传递
├─ 网络:STREAM,TAP tk0 ↔ 宿主 smoltcp
└─ FUSE:每个挂载一个 socketpair,宿主 FuseHost 服务
- 无守护进程、无服务、不需要 root。 每个
Sandbox拥有独立的 bwrap+init 组合。 - 打包 rootfs。
/usr /bin /sbin /lib /lib64 /etc/passwd /etc/group都来自.vm/base/rootfs/(与 macOS、Windows 启动用的同一份 artifact),保证三平台 sandbox 内看到同一套工具版本。仅网络/DNS/CA 配置仍从宿主机绑定。 - 网络:
AllowAll和Blocked都使用--unshare-net创建全新网络命名空间。AllowAll通过 TAP 设备(tk0)叠加 smoltcp 用户态网络栈,经 STREAM socketpair 桥接到宿主——与 macOS 和 Windows 架构完全一致。Blocked只有lo。 - 文件共享: 所有挂载使用 FUSE-over-socketpair —— 与 macOS 和 Windows 共同一套
FuseHost+tokimo-sandbox-fuse基础设施。每个挂载获得一个AF_UNIX SOCK_STREAMsocketpair;宿主端由FuseHost服务,客机端通过--transport unix-fd传递给tokimo-sandbox-fuse。启动时和运行时挂载使用相同机制。 - PTY: 主 fd 通过
SCM_RIGHTS传递到宿主,直接 I/O。
Sandbox::start_vm()
│
└─ arcbox-vz → VZVirtualMachine
├─ VZLinuxBootLoader(vmlinuz, initrd.img)
├─ VZVirtioFileSystemDevice tag="rootfs" ← rootfs(只读)
├─ VZVirtioSocketDevice port=2222 ← init 控制通道
├─ VZVirtioSocketDevice port=4444 ← 用户态网络栈
├─ VZVirtioSocketDevice port=5555 ← FUSE-over-vsock 宿主
└─ VZNetworkDeviceConfiguration::nat() ← 仅 AllowAll
│
└─ Linux 微型虚拟机(arm64)
tokimo-sandbox-init(PID 1)通过 virtio-vsock 通信
- 无服务、不需要 root。 纯库调用;每个
Sandbox启动自己的虚拟机。 - 共享文件系统: 所有挂载使用 FUSE-over-vsock —— 宿主在 vsock 端口 5555 上运行进程内
FuseHost,每个挂载在客机中启动一个tokimo-sandbox-fuse子进程通过 vsock 连回。与 Linux 和 Windows 共同一套基础设施。 - 网络:
AllowAll使用宿主侧 smoltcp 用户态网络栈(vsock 传输)。Blocked从虚拟机配置中省略网络设备。 - PTY: 主 fd 留在客机中;init 通过协议
Stdout/Write事件桥接 I/O。
Sandbox(库) ──命名管道──▶ tokimo-sandbox-svc.exe(SYSTEM)
│
├─ HCS 计算系统(Schema 2.5)
│ ├─ LinuxKernelDirect(vmlinuz, initrd)
│ ├─ SCSI:每会话 rootfs.vhdx
│ ├─ FUSE-over-vsock(用户挂载)
│ └─ HvSocket ServiceTable
│
├─ AF_HYPERV 监听器(每会话 GUID)
│
└─ smoltcp 用户态网络栈
│
└─ NAT → 宿主网络
- SYSTEM 服务代表非特权用户管理虚拟机。通过
sudo ... --install或 MSIX 一次性安装。 - 每会话隔离: 每个会话获得独立的 VHDX 克隆和 HvSocket 服务 GUID,支持并发会话。
- 网络:
AllowAll使用与 macOS 相同的 smoltcp 用户态网络栈。Blocked在内核参数中设置tokimo.net=blocked。 - PTY: 与 macOS 相同——主 fd 留在客机,I/O 通过协议桥接。
所有后端的 AllowAll 策略使用同一套 smoltcp L3/L4 代理(src/net/netstack/)。一套统一的网络栈,一个拦截点,不区分平台或 Linux 后端。
Linux 客机内核
│ 以太网帧
│ Linux bwrap:通过 TAP tk0 → STREAM socketpair
│ Linux ch: 通过 TAP tk0 → vsock UDS sidecar
│ macOS: 通过 virtio-vsock
│ Windows: 通过 HvSocket
▼
StreamDevice(smoltcp,宿主侧)
│
├─ TCP:smoltcp socket → 宿主 TcpStream::connect() → 双向代理
├─ UDP:smoltcp socket → 宿主 UdpSocket → 手动构造以太网回复帧
└─ ICMP:解析 EchoRequest → 平台特定 send_echo → 构造 EchoReply
- 所有后端统一 —— Linux bwrap(TAP + socketpair)、Linux ch(TAP + vsock)、macOS(vsock)、Windows(HvSocket)
- 双栈 IPv4/IPv6,支持扩展头遍历(HopByHop、Route、Opts、Frag)
- 子网: 192.168.127.0/24(v4)、fd00:7f::/64(v6),MTU 1400
- 3 线程: RX 读取(传输层 → smoltcp)、主轮询循环、TX 写入(smoltcp → 传输层)
- 120 秒空闲超时(每流)
tokimo-sandbox-init 是一个 Rust 二进制,在每个沙箱中以 PID 1(或 bwrap 中的 PID 2)运行。启动时自动检测传输层:
| 传输层 | 使用者 | PTY 机制 |
|---|---|---|
SOCK_SEQPACKET(继承 fd) |
Linux bwrap | SCM_RIGHTS fd 传递 |
SOCK_SEQPACKET(监听器) |
Linux 独立模式 | SCM_RIGHTS fd 传递 |
| VSOCK 流(客机连接) | Linux ch(hybrid-vsock) | 协议桥接(Stdout/Write 事件) |
| VSOCK 流(客机监听) | macOS VZ | 协议桥接(Stdout/Write 事件) |
| VSOCK 流(客机连接) | Windows HCS | 协议桥接(Stdout/Write 事件) |
能力:Pipes 和 Pty stdio 模式、Resize、Signal、Killpg、OpenShell、MountFuse/UnmountFuse(FUSE-over-vsock/socketpair)。
[dependencies]
tokimo-package-sandbox = "0.1"use tokimo_package_sandbox::{Sandbox, ConfigureParams, NetworkPolicy};
let sb = Sandbox::connect().unwrap();
sb.configure(ConfigureParams {
user_data_name: "demo".into(),
memory_mb: 4096,
cpu_count: 4,
network: NetworkPolicy::AllowAll,
..Default::default()
}).unwrap();
sb.create_vm().unwrap();
sb.start_vm().unwrap();
let shell = sb.shell_id().unwrap();
sb.write_stdin(&shell, b"uname -a\n").unwrap();
// ... 通过 sb.subscribe() 读取事件 ...
sb.stop_vm().unwrap();| 平台 | 要求 |
|---|---|
| Linux | bwrap 后端:sudo apt install bubblewrap。ch 后端:需要 cloud-hypervisor + virtiofsd 二进制在 PATH 上(或位于 bin/cloud-hypervisor/current/bin/ 与 bin/virtiofsd/current/),/dev/kvm 与 /dev/vhost-vsock 可访问(通常需要用户在 kvm 组中)。需要 <repo>/.vm/base/ 下的虚拟机产物。两种后端运行时都不需要 root。 |
| macOS | macOS 13+,Apple Silicon。需要 <repo>/.vm/base/ 下的虚拟机产物(见下方)。代码签名需要 com.apple.security.virtualization 权限。 |
| Windows | 启用"虚拟机平台"(Win 10 1903+)。一次性 sudo 安装服务。需要 <repo>/.vm/base/ 下的虚拟机产物。 |
三个后端共享同一套 Linux 内核 + initrd + Debian 13 rootfs。内核+initrd 与 rootfs 通过两个独立 tag 系统发布:vm-kernel-* 跟随 host crate 版本,vm-rootfs-* 很少重发。下载:
# Linux / WSL
scripts/linux/fetch-vm.sh # 最新发布
scripts/linux/fetch-vm.sh -k vm-kernel-1.0.0 -r vm-rootfs-1.0.0 # 指定标签# Windows
pwsh scripts/windows/fetch-vm.ps1 # 最新发布
pwsh scripts/windows/fetch-vm.ps1 -KernelTag vm-kernel-1.0.0 -RootfsTag vm-rootfs-1.0.0macOS 本地构建:
scripts/macos/build-vm-local.sh # arm64(默认)发布的 initrd 由 CI (vm.yml → build.sh) 构建,是 kernel + modules
- rootfs 的唯一权威来源。当你在迭代
init.sh或三个 musl 业务二进制 (tokimo-sandbox-init、tokimo-tun-pump、tokimo-sandbox-fuse)时, 不需要重跑完整流水线,只需把它们换进发布版 initrd 的副本:
# Linux
scripts/linux/rebake-initrd.sh --install-to-vm
# macOS(exec 上面那个 — guest 二进制始终是 Linux musl)
scripts/macos/rebake-initrd.sh --install-to-vm# Windows(pwsh → wsl bash 上面那个)
pwsh scripts/windows/rebake-initrd.ps1 -InstallToVm三个入口接受同一组 flag:--skip-build、--install-to-vm、
--arch amd64|arm64、--base <path>。Rebake 永远不会动 /modules/
—— 内核模块从 CI 出来时 vermagic 已与 vmlinuz 严格匹配,脚本最后会对
刚生成的 initrd 跑 vermagic 自检确认。
在本地 .cargo/config.toml 中注册签名 cargo runner:
[target.aarch64-apple-darwin]
runner = "scripts/macos/codesign-and-run.sh"# 开发 — 前台运行,无 SCM
sudo cargo run --bin tokimo-sandbox-svc -- --console
# 开发 — 持久化 SCM 服务(sudo)
sudo .\target\debug\tokimo-sandbox-svc.exe --install
# 生产 — MSIX
pwsh scripts/windows/build-msix.ps1所有平台运行相同的 Debian 13(Trixie)Linux rootfs:
| 类别 | 内容 |
|---|---|
| 运行时 | Node.js 24、Python 3.13、Lua 5.4 |
| 编辑器 | vim、nano |
| 办公/文档 | pandoc、libreoffice(headless)、poppler、qpdf、tesseract-ocr |
| Python | pypdf、pdfplumber、reportlab、pandas、openpyxl、markitdown、ipython、requests、rich、Pillow |
| Node.js | pnpm、docx、pptxgenjs |
| 媒体 | ffmpeg |
| 网络 | curl、wget、dig、ping、rsync、git |
| 其他 | jq、zstd、bash-completion |
let sb = Sandbox::connect()?;
sb.configure(ConfigureParams { .. })?;
sb.create_vm()?; // Windows:HCS 计算系统;Linux/macOS:无操作
sb.start_vm()?; // Linux:启动 bwrap;macOS:启动虚拟机;Windows:启动 HCS
sb.stop_vm()?; // 销毁let shell = sb.shell_id()?; // 默认 shell
let job = sb.spawn_shell(ShellOpts { pty: Some((24, 80)), .. })?; // PTY shell
sb.write_stdin(&shell, b"echo hello\n")?;
sb.resize_shell(&job, 40, 120)?;
sb.signal_shell(&job, Signal::SIGTERM)?;
sb.close_shell(&job)?;
let shells = sb.list_shells()?;let rx = sb.subscribe();
for event in rx {
match event {
Event::Stdout { id, data } => { /* stdout 字节 */ }
Event::Stderr { id, data } => { /* stderr 字节 */ }
Event::Exit { id, exit_code, signal } => { /* 进程退出 */ }
Event::GuestConnected => { /* 客机 init 就绪 */ }
_ => {}
}
}sb.add_mount(Mount {
name: "workspace".into(),
host_path: "/tmp/my-project".into(),
guest_path: "/workspace".into(),
read_only: false,
})?;
// ... 客机可以访问 /workspace ...
sb.remove_mount("workspace")?;34 个集成测试,通过公共 Sandbox API 测试真实客机。平台无关的源码;同一套测试在三个平台上运行。
# Linux —— bwrap 后端
sudo apt install bubblewrap
cargo build --bin tokimo-sandbox-init
SANDBOX_BACKEND=bwrap PATH="$PWD/target/debug:$PATH" \
cargo test --test sandbox_integration -- --test-threads=1
# Linux —— ch 后端(KVM 微型虚拟机;需要 cloud-hypervisor + virtiofsd + /dev/kvm)
SANDBOX_BACKEND=ch PATH="$PWD/target/debug:$PATH" \
cargo test --test sandbox_integration -- --test-threads=1
# macOS
cargo test --test sandbox_integration -- --test-threads=1
# Windows(sudo,服务运行中)
sudo cargo test --test sandbox_integration -- --nocaptureLinux(bwrap 用户命名空间速率限制;CH 启动序列化)和 macOS(VZ 调度队列串行化虚拟机启动)必须使用 --test-threads=1。Windows 支持并发。
覆盖范围:生命周期、Shell I/O、多 Shell 流 + 信号 + 枚举、PTY 大小/调整/ctrl-c/转义序列、FUSE 挂载添加/移除、网络 blocked/allow-all/ICMPv4/ICMPv6/IPv6 TCP、多会话并发。
单元测试:cargo test --lib(会话注册表、协议、服务内部)。
# 沙箱内交互式 PTY shell
cargo run --example pty_shell
# smoltcp 网络栈独立演示(无虚拟机的 TCP + UDP 代理)
cargo run --example smoltcp_netstacksrc/
├── lib.rs Crate 根:7 个顶层模块,向后兼容 re-export shim
│
├── api/ 公共 Sandbox API
│ ├── mod.rs Sandbox 句柄(~30 个方法)、ConfigureParams、ShellOpts、
│ │ Mount、NetworkPolicy、Event、HostExecCtx/Action/Callback、
│ │ JobId、SessionSummary/Details、PortForwardSpec
│ ├── backend.rs SandboxBackend trait — 每平台实现契约
│ ├── backend_kind.rs SandboxBackendKind(Auto/Disabled/Bwrap/Ch)、ActiveBackend
│ ├── error.rs Error 枚举 + Result 别名 + bail! 宏
│ └── platform.rs 每平台 default_backend()
│
├── backends/ 平台特定后端实现
│ ├── mod.rs 条件编译:linux、macos、shared、svc_protocol、windows
│ ├── shared.rs SharedBackend<B> — 进程级会话共享(Linux/macOS)
│ ├── svc_protocol.rs Windows 宿主 ↔ 服务 JSON-RPC 协议
│ ├── linux/
│ │ ├── bwrap/ bubblewrap 后端(无虚拟机,仅命名空间)
│ │ │ ├── sandbox.rs LinuxBackend: SandboxBackend
│ │ │ ├── init_client.rs InitClient(SOCK_SEQPACKET)
│ │ │ └── init_transport.rs SEQPACKET 帧 + SCM_RIGHTS
│ │ └── ch/ Cloud Hypervisor 微型虚拟机后端
│ │ ├── backend.rs ChBackend: SandboxBackend
│ │ ├── vmm.rs CH + virtiofsd 子进程生命周期
│ │ └── probe.rs probe_ch() — KVM/vsock/二进制可用性检查
│ ├── macos/
│ │ ├── sandbox.rs MacosBackend: SandboxBackend
│ │ ├── vm.rs VZ 虚拟机生命周期、BOOT_LOCK
│ │ └── vsock_init_client.rs VsockInitClient(VSOCK 传输)
│ └── windows/
│ ├── sandbox.rs WindowsBackend: SandboxBackend(命名管道 JSON-RPC)
│ ├── client.rs 命名管道客户端
│ ├── init_client.rs 透明管道隧道上的 init 客户端
│ ├── init_transport.rs Windows init 传输层适配
│ ├── ov_pipe.rs OVERLAPPED Read/Write 封装
│ ├── safe_path.rs TOCTOU 安全的 canonicalize_safe
│ └── ntfs_mode.rs NTFS mode-bit 辅助函数
│
├── init/ 宿主侧 init 客户端 + 协议(所有后端共享)
│ ├── client/
│ │ ├── mod.rs InitClient<S: TransportSend> — 泛型宿主侧客户端
│ │ └── vsock.rs VSOCK 传输实现
│ └── protocol/
│ ├── types.rs Frame、Op、Reply、Event、StdioMode
│ └── wire.rs 帧编解码、SEQPACKET + 流传输辅助
│
├── vfs/ VFS 子系统(FUSE-over-vsock/socketpair)
│ ├── backend.rs VfsBackend trait 层次结构 + VfsFileInfo
│ ├── protocol/
│ │ ├── mod.rs VFS 线路协议:Frame、Req(~35 个操作)、Res、Errno
│ │ ├── wire.rs 长度前缀 postcard 帧 + bulk-bypass 优化
│ │ └── handshake.rs Hello/HelloAck 握手
│ ├── host/
│ │ ├── mod.rs FuseHost:accept 循环、每挂载分发
│ │ ├── id_table.rs Nodeid + fh 分配器(带引用计数)
│ │ └── ops/ 每操作处理器:dir、file、meta、mutate、xattr
│ └── impls/
│ ├── local.rs LocalDirVfs — 宿主目录透传
│ ├── mem.rs MemFsVfs — 内存文件系统(测试用)
│ ├── meta.rs meta_to_info() 辅助函数
│ ├── sanitize.rs 路径清理
│ └── macos_xattr.rs macOS xattr 处理
│
├── net/ 网络
│ ├── constants.rs 共享拓扑常量(IP、MAC、子网、MTU)
│ ├── ifreq.rs Linux ioctl 辅助函数
│ └── netstack/
│ ├── mod.rs 用户态 smoltcp L3/L4 代理(~1750 行)
│ ├── host_dns.rs 宿主 DNS 解析器检测
│ └── icmp/ 平台特定 ICMP echo 后端
│
├── host_exec/ Host-Exec 桥接(客机命令 → 宿主回调)
│ ├── mod.rs HostExecBridge、BridgeStream trait、handle_one()
│ ├── linux_relay.rs SCM_RIGHTS 中继读取线程
│ ├── macos_listener.rs vsock accept 循环
│ ├── transport.rs 传输层抽象
│ └── protocol/
│ ├── mod.rs 线路协议:Frame 枚举、版本 1
│ └── wire.rs Postcard 帧封装
│
├── util/ 工具函数
│ ├── affinity.rs CPU 亲和性辅助
│ ├── fonts.rs 宿主字体目录发现
│ ├── raw_io.rs 底层 I/O 辅助(Unix)
│ ├── rootfs_init.rs Rootfs 初始化
│ ├── session_registry.rs SessionRegistry(Windows 服务)
│ ├── vm_dir.rs 虚拟机目录管理
│ └── vsock_util.rs VSOCK 连接辅助(Linux)
│
└── bin/
├── tokimo-sandbox-init/ 客机 PID 1 二进制(三平台共用)
│ ├── main.rs 传输层分发、挂载设置、chroot
│ ├── server.rs 主请求循环(mio::Poll)
│ ├── child.rs 子进程管理
│ ├── pty.rs PTY 分配
│ └── pump.rs TUN ↔ vsock 桥接
│
├── tokimo-sandbox-fuse/ 客机侧 FUSE 桥接二进制
│ └── main.rs 内核 FUSE 操作 → VFS 线路请求
│
├── tokimo-sandbox-svc/ Windows SYSTEM 服务
│ └── imp/
│ ├── mod.rs SCM 生命周期、管道服务器、会话处理
│ ├── hcs.rs ComputeCore.dll 加载器
│ ├── hvsock.rs AF_HYPERV socket 辅助
│ ├── vmconfig.rs HCS Schema 2.5 JSON 构建器
│ ├── vhdx_pool.rs 每会话 VHDX 租赁
│ ├── netstack.rs smoltcp 用户态网络栈
│ └── svclog.rs 日志
│
├── tokimo-tun-pump/ 客机侧 TUN ↔ vsock 桥接
└── tokimo-host-exec/ 客机侧 host-exec 桩
| 策略 | 行为 |
|---|---|
AllowAll(默认) |
通过 smoltcp 用户态网络栈 提供完整网络访问(所有后端)。Linux bwrap:TAP + socketpair。Linux ch:TAP + vsock。macOS:vsock。Windows:HvSocket。 |
Blocked |
无网络。Linux bwrap:仅有 lo 的新网络命名空间。Linux ch:CH 配置中无网卡。macOS:虚拟机配置中无网卡。Windows:内核参数 tokimo.net=blocked。 |
| tokimo-package-sandbox | Docker | |
|---|---|---|
| 守护进程 | 无(库调用;Windows 上为 SYSTEM 服务) | 需要 dockerd |
| 启动速度 | ~50 ms(Linux)/ ~2 s 冷启动(macOS/Windows 虚拟机) | ~1-3 s |
| Root | 不需要(Linux/macOS) | 通常需要 |
| 镜像 | 无(内置 Debian rootfs) | 需要 |
| API | Rust 原生,Sandbox 句柄 |
CLI / REST |
| 网络 | 统一 smoltcp 用户态网络栈(所有平台) | bridge + iptables NAT |
| 用途 | "运行这条不受信任的命令" | "部署这个服务栈" |
MIT。见 LICENSE。