将容器变成真正的沙箱

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文讲的是将容器变成真正的沙箱,【编者的话】本文来自于Jessie Frazelle的博客,原文链接here。
本文讲的是将容器变成真正的沙箱 【编者的话】本文来自于Jessie Frazelle的博客,原文链接 here

容器现在非常流行,其最核心之处所使用的Linux原语和创建应用程序沙箱是一致的。大家比较熟悉的沙箱技术可能是Chrome沙箱,关于Chrome沙箱的详细介绍可以访问链接 chromium.googlesource.com/chromium/src/+/master/docs/linux_sandboxing.md ,其中与本文比较相关的是它使用了用户命名空间技术和seccomp机制,以及其他一些已经弃用的功能,包括AppArmor和SELinux。听起来有些熟悉?那是因为今天我们所了解的容器技术都使用了这些相同的功能。

为什么现在容器没有被认为是一个“沙箱”?

运行Chrome沙箱和运行容器的关键不同点之一在于权限的使用。Chrome沙箱以非特权用户身份运行,而大多数容器(例如docker、runc或者rkt)以root用户身份运行。

当然,我们都知道容器里运行的都是非特权进程,但是创建和启动容器在某些地方是需要使用root特权。

怎么以非特权用户运行容器?

你可能会说,非常容易,使用用户命名空间啊!但事实上没有这么简单。Chrome沙箱和容器的主要区别之一在于cgroups。Cgroups控制的是进程所能够使用的资源,而命名空间控制的是进程的可见范围。容器内嵌了cgroup资源管理,使用非特权用户创建cgroups是比较困难的,特别是设备控制组。

如果我们暂时忽略“使用非特权用户创建cgroups”这个难题,那使用非特权用户创建容器就简单了。用户命名空间技术允许我们在不使用任何特权的情况下创建所有命名空间,唯一需要提醒的是 {uid,gid}_map 必须将宿主机当前用户映射为容器内进程运行所使用的uid, {uid,gid}_map 的大小可以只设置为1。比如说,你使用uid为1000的用户来创建容器, {uid,gid}_map 设置为 0 1000 1 ,即表示在容器内以uid为0的用户身份来运行进程,而1指的是 {uid,gid}_map 的大小。

Docker对于用户命名空间的支持有什么不同?

Docker对于用户命名空间的支持与上述方式完全不同。默认情况下,当重映射用户被创建时, /etc/subuid /etc/subgid 这两文件将连续地写入65536范围以内从属用户和组的ID,起始ID的偏移量从这些文件当前条目开始计算。Docker的实现让更大范围的用户能够存于容器中,甚至可以让“匿名”用户来映射宿主机用户。如果你想了解更多关于Docker用户命名空间的实现,推荐 estesp 的博客或者Docker的 官方文档

POC或者GTFO

为了证明在不使用cgroups情况下实现非特权容器的想法,我创建了 binctr 。我在谷歌论坛上也建了一个帖子来讨论如何在runc或者libcontainer中实现这个想法,具体可见 here Aleksa Sarai 已经开始提交代码,这可能很快就会成为一个现实。

这是否处于“沙箱”范畴?

通过实现,我们将
  • namespaces
  • apparmor
  • selinux
  • seccomp
  • capabilities limiting

这些都使用非特权用户进行创建!

沙箱应该是比较面向具体应用的,使用定制的AppArmor配置文件、Seccomp配置文件等等。通用容器决不会等价于沙箱,因为它过于普遍而不能真正地锁定应用程序。

容器并不能够完全防止你的应用程序受到危害,但它能够限制受到危害的程度。攻击者在一个拥有定制AppArmor或Seccomp配置文件且十分严谨的容器中所看到的与不使用容器所看到的是完全不同的世界。通过命名空间我们可以限制应用程序的可见范围,例如网络、挂载点、进程等等。而且通过cgroups我们能够进一步限制攻击者所能够使用的资源,无论是内存、cpu,还是fork原语。

但关于cgroups呢?

我们可以使用非特权用户给内存、blkio、cpu和pids建立cgroups,只要cgroup子系统的所有者被修改为当前用户。设备却是另外一回事,不过无法在一个用户命名空间中使用mknod并不是世界上最糟糕的事情。

我们不要完全把设备cgroup排除,将来完全有可能实现。4.6版本以上的内核,将会有一种新的cgroup命名空间。而现在的做法就是在容器内掩盖了cgroups路径,所以对于非特权容器来说不是完全有用。但未来也许可以(如果我们的要求足够好?)

这个想法带给我们的最棒收益是什么?

GitHub上讨论非特权runc容器这个问题的评论者中大多数都是来源于一些科学社区,他们都严格地被要求使用非root用户来运行程序。

但是这个想法的用处远不止于这个。我最期盼的用法之一就是 Alex Larsson xdg-app 所完成的工作,即在沙箱中运行应用程序。如果感兴趣的话可以了解下 bubblewrap

还有 subgraph ,基于OS的容器专门用于安全和隐私方面,和我们有着相同的想法。

对于在容器中运行桌面应用以及解决容器的多租户问题我都有非常大兴趣,我衷心希望能够帮助容器发展成一个真正的沙箱。

原文链接:Getting Towards Real Sandbox Containers(翻译:肖远昊)

原文发布时间为:2016-05-14
本文作者:xiaoyh
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:将容器变成真正的沙箱
目录
相关文章
|
Kubernetes 安全 Cloud Native
安全容器:开启云原生沙箱技术的未来
本文中,蚂蚁金服和阿里云的容器开发者们会共同向大家介绍安全容器的前世今生、它们在 双11 中的应用、以及未来的发展方向。
安全容器:开启云原生沙箱技术的未来
|
2月前
|
存储 监控 测试技术
如何将现有的应用程序迁移到Docker容器中?
如何将现有的应用程序迁移到Docker容器中?
255 57
|
2月前
|
存储 监控 Java
如何对迁移到Docker容器中的应用进行性能优化?
如何对迁移到Docker容器中的应用进行性能优化?
248 59
|
2月前
|
NoSQL Redis Docker
使用Docker Compose工具进行容器编排的教程
以上就是使用Docker Compose进行容器编排的基础操作。这能帮你更有效地在本地或者在服务器上部署和管理多容器应用。
313 11
|
2月前
|
缓存 Java Docker
如何对应用代码进行优化以提高在Docker容器中的性能?
如何对应用代码进行优化以提高在Docker容器中的性能?
204 1
|
3月前
|
Docker 容器
Docker网关冲突导致容器启动网络异常解决方案
当执行`docker-compose up`命令时,服务器网络可能因Docker创建新网桥导致IP段冲突而中断。原因是Docker默认的docker0网卡(172.17.0.1/16)与宿主机网络地址段重叠,引发路由异常。解决方法为修改docker0地址段,通过配置`/etc/docker/daemon.json`调整为非冲突段(如192.168.200.1/24),并重启服务。同时,在`docker-compose.yml`中指定网络模式为`bridge`,最后通过检查docker0地址、网络接口列表及测试容器启动验证修复效果。
|
1月前
|
安全 持续交付 Docker
Docker:重塑现代软件交付的容器引擎
Docker:重塑现代软件交付的容器引擎
|
1月前
|
运维 测试技术 Docker
Docker:轻量级容器化技术革命
Docker:轻量级容器化技术革命
|
1月前
|
存储 持续交付 Docker
Docker:颠覆传统开发的轻量级容器革命
Docker:颠覆传统开发的轻量级容器革命