毕设──基于虚拟机的智能体沙箱的设计与实现(1)
最近一直在学习 C++ 的代码相关知识。因为马上要交开题报告了,所以找了个空闲的时间看了下毕设相关的内容。
毕设就是个 Agent 代码执行沙箱,为什么要选这个题目呢?第一是对虚拟机这方面挺感兴趣的,第二就是之前在红队做过针对 Agent 代码执行的攻击,有一定了解。
技术方案选型
目前阶段主要还是去选择用啥去实现这个沙箱,目前的话主要是试试下面这几种:
1. WASM
启动很快,因为是进程级别的虚拟机,不涉及虚拟化乱七八糟的,开销很小,就是把不同语言编译为可以跑在 WASM 虚拟机上的字节码。
默认权限很小,只有纯计算和调用显式提供 API 的能力。但是兼容性不行,语言支持受限(尤其是本来就跑在虚拟机上的语言,需要把它的虚拟机编译为 WASM,然后跑在 WASM 虚拟机上),系统调用受限。并且不像 Docker,想要什么镜像直接拉下来就行,得去将想运行的组件编译为 WASM。
2. Docker
Docker 主要就是选运行时:
runc:用 Linux 的 Namespace 和 Cgroups 做隔离、资源限制,不涉及虚拟化。好处就是快,缺点就是不够安全,因为内核共享,内核漏洞可以打到真实内核上,进而造成逃逸。
Kata Containers:有独立的裁剪内核,跑在 QEMU/Firecracker 上。这个是唯一一个具有真正独立操作系统内核的方案,代码跑在 QEMU/Firecracker 运行的操作系统上,运行在 VMX non-root 区域。这个方案安全性、兼容性很好,那么相对的,启动慢、开销大,因为它要从头引导一个操作系统。
gVisor:用 Go 语言实现了一个运行在用户态的内核 Sentry,通过 ptrace 或 KVM 拦截容器的系统调用,大部分由 Sentry 自己处理,只有少数才会进入实际的 Linux 内核。首先它重新实现的肯定修了漏洞,其次就算被打了,也只是用户态的 Sentry 进程,这个进程只管理当前这一个容器,危害相对较小。这个属于折中的方案。
WasmEdge:WASM 同时也可以塞在 Docker 里面,优缺点不变。
3. 参考 E2B 实现
参考 E2B 的架构,底层直接使用 Firecracker 微虚拟机,自行实现对 Firecracker 的编排调度。
相比 Kata Containers 等其他具有独立内核的方案,Firecracker 的核心优势在于其快照机制:可以预先启动一个配置好环境的虚拟机,然后对其内存和设备状态进行快照保存。后续需要新实例时,直接从快照恢复,跳过整个操作系统引导过程,从而解决冷启动问题。而其他需要独立内核的方案(如 Kata + QEMU)每次都需要从头引导一个操作系统内核,启动时间较长。
测试
首先尝试了 Docker + Kata Containers + QEMU,测试如下:




