我正在开发一个实现分布式模拟的项目:随意的代码在多个节点上执行,然后收集并聚合结果。
每个节点都是 Ubuntu Linux 虚拟机的一个实例,并运行一个主进程,该进程负责将要执行的代码转发到多个工作进程(每个核心 1 个)。
这个问题是关于如何确保每个工作人员在沙盒环境中运行,而不需要为每个工作人员使用虚拟机实例。对工人的具体要求是:
- FS:无写权限,只读权限仅限于单个目录(及子文件夹)
- 网:仅允许本地通信(IPC、TCP,等等......)
- 内存:内存使用上限(无交换内存)如果超过内存限制则终止
- 中央处理器:只允许1个核心,如果超过时间限制则终止
不应施加其他限制:工作线程应该能够加载动态库(从只读文件夹),生成新线程或进程,调用系统函数,ecc ecc,但限制必须由生成/加载的实体继承,并且应该以求和方式应用(例如,我们不能让一个工作线程生成两个线程,每个线程使用 800MB,因为该工作线程的内存限制为 1GB)。
不言而喻,工人应该没有办法提高自己的权利。
我花了相当多的时间来审查可用的替代方案(SELinux、AppArmor、cgroups、ulimit、Linux 命名空间、LXC、Docker 等),寻找满足我的要求的最简单的解决方案,但我在该领域的经验有限。
目前的理解:对于我的用例来说,LXC 和 Docker 有点重,而且并不完全安全1。 AppArmor 比 SELinux 更好,因为配置更容易,使用它来限制文件系统和网络; cgroups 优于 ulimit(在单个进程上运行),将其用于 mem 和 cpu 限制。
这是实现我的目标的最简单方法吗?我可以专门使用 AppArmor 或 cgroups 吗?我的模型中是否存在明显的安全漏洞?指导方针应该是“工人被允许摔倒自己,但不能摔倒其他任何东西”。
答案1
是的,您可以专门使用 cgroups 和 SELinux/AppArmor 来监视和控制随意的您将执行的代码。
使用 cgroup,您可以执行以下操作:
cpuset
将子系统的 CPU 核心使用限制为 1 个 CPU- 设置内存使用限制
memory
子系统设置内存使用限制,甚至跟踪分叉。看https://github.com/gsauthof/cgmemtime举个例子。 - 防止网络访问任何未
lo
与net_prio
子系统连接的内容。
通过 SELinux/AppArmor,您可以限制进程的读/写访问权限。
注意:我不熟悉AppArmor,但它是一个强制访问控制(MAC)系统,这意味着保护写入和读取是它的工作。
使用这些系统只需编写正确的配置即可。当然,这一切说起来容易做起来难。因此,这里有一些参考链接可以帮助您入门:
祝你好运!
答案2
我会丢弃SELinux为了应用装甲仅当我使用时乌班图。 (确实相当困难)
LXC本身并不安全如果您需要安全性,则必须通过以下方式使用它们库虚拟机(基于SELinux MLS)。
你的问题是无穷因此,不要试图在没有无限时间的情况下寻找现成的解决方案,请记住,即使内核.org被骗了,最近联邦调查局声称有人多年来一直在使用他们的系统,直到现在才被发现。
我会和LXC/libvirt为了获得很好的安全性,否则我会尝试“新”英特尔透明容器,为您的容器使用非常轻的虚拟机,并明确使用德国DAX/KSM(我还没有测试过它们,但它们看起来确实很有前途)。
如果您担心内核漏洞利用,网络安全是您的解决方案,但您必须将其与容器解决方案集成(肯定令人头痛)。
所以这肯定不是一件容易的事,LXC/libvirt确实很整洁,但也许透明的容器才是正确的选择。
码头工人?当没有可用的 vagrant box 时,我没有/不会使用 docker 进行本地测试以外的其他操作,他们需要更多的工作和更好的社区。
当然,systemd 容器也很好,但我假设您不喜欢/不想要它们,因为您甚至没有提到它们,而且它们不是与供应商无关的解决方案。
如果你想要一些“更简单”和更业余的东西,你可以看看消防监狱,我一直在一些桌面“应用程序”中使用它,它完成了这项工作(为您的自定义应用程序创建模板非常容易,在目录顶部使用“私有”安装并限制网络仅供本地使用,生成的进程继承父进程并继续...)。
干杯并享受乐趣而不发疯。 ;)
答案3
seccomp-bpf 是另一个适用于 OpenSSH、vsftpd 和 Chromium 的选项,它只有 exit()、sigreturn()、read(),它也使用 write(),尽管它允许使用可配置的 Berkeley Packet Filter 规则过滤系统调用。它还可以与内存、CPU 等的 cgroup 结合使用......
答案4
您可能想研究网格计算系统。特别是,BOINC(http://boinc.berkeley.edu)检查几乎所有的方框。
我相信它会根据您的参数运行:
fs:可以读/写到它自己的目录,而不是其他目录
net:可以配置为仅允许网络访问您的 BOINC 服务器,但不是默认的开箱即用 IIRC
mem:是的,空闲和非空闲机器的单独内存限制
cpu:是的,甚至可以说“如果计算机不空闲就不要运行”