前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >隔离 Docker 容器中的用户

隔离 Docker 容器中的用户

作者头像
星哥玩云
发布于 2022-07-19 08:32:12
发布于 2022-07-19 08:32:12
3.5K1
举报
文章被收录于专栏:开源部署开源部署

笔者在前文《理解 docker 容器中的 uid 和 gid》介绍了 docker 容器中的用户与宿主机上用户的关系,得出的结论是:docker 默认没有隔离宿主机用户和容器中的用户。如果你已经了解了 Linux 的 user namespace 技术(参考《Linux Namespace : User》),那么自然会问:docker 为什么不利用 Linux user namespace 实现用户的隔离呢?事实上,docker 已经实现了相关的功能,只是默认没有启用而已。笔者将在本文中介绍如何配置 docker 来隔离容器中的用户。 说明:本文的演示环境为 Ubuntu 16.04。

了解 Linux user namespace

Linux user namespace 为正在运行的进程提供安全相关的隔离(其中包括 uid 和 gid),限制它们对系统资源的访问,而这些进程却感觉不到这些限制的存在。关于 Linux User Namespace 的介绍请参考笔者的《Linux Namespace : User》一文。

对于容器而言,阻止权限提升攻击(privilege-escalation attacks)的最好方法就是使用普通用户权限运行容器的应用程序。 然而有些应用必须在容器中以 root 用户来运行,这就是我们使用 user namespace 的最佳场景。我们通过 user namespace 技术,把宿主机中的一个普通用户(只有普通权限的用户)映射到容器中的 root 用户。在容器中,该用户在自己的 user namespace 中认为自己就是 root,也具有 root 的各种权限,但是对于宿主机上的资源,它只有很有限的访问权限(普通用户)。

User namespace 的用户映射

在配置 docker daemon 启用 user namespace 前,我需要先来了解一些关于从属(subordinate)用户/组和映射(remapping)的概念。从属用户和组的映射由两个配置文件来控制,分别是 /etc/subuid 和 /etc/subgid。看下它们的默认内容:在配置 docker daemon 启用 user namespace 前,我需要先来了解一些关于从属(subordinate)用户/组和映射(remapping)的概念:

对于 subuid,这一行记录的含义为: 用户 nick,在当前的 user namespace 中具有 65536 个从属用户,用户 ID 为 100000-165535,在一个子 user namespace 中,这些从属用户被映射成 ID 为 0-65535 的用户。subgid 的含义和 subuid 相同。

比如说用户 nick 在宿主机上只是一个具有普通权限的用户。我们可以把他的一个从属 ID(比如 100000 )分配给容器所属的 user namespace,并把 ID 100000 映射到该 user namespace 中的 uid 0。此时即便容器中的进程具有 root 权限,但也仅仅是在容器所在的 user namespace 中,一旦到了宿主机中,你顶多也就有 nick 用户的权限而已。

当开启 docker 对 user namespace 的支持时(docker 的 userns-remap 功能),我们可以指定不同的用户映射到容器中。比如我们专门创建一个用户 dockeruser,然后手动设置其 subuid 和 subgid:

nick:100000:65536 dockeruser:165536:65536

并把它指定给 docker daemon:

{   "userns-remap": "dockeruser" }

请注意 subuid 的设置信息,我们为 dockeruser 设置的从属 ID 和 nick 用户是不重叠的,实际上任何用户的从属 ID 设置都是不能重叠的。

或者一切从简,让 docker 为我们包办这些繁琐的事情,直接把 docker daemon 的 userns-rempa 参数指定为 "default":

{   "userns-remap": "default" }

这时,docker 会自动完成其它的配置。

配置 docker daemon 启用用户隔离

这里笔者采取简单的方式,让 docker 创建默认的用户用于 user namespace。我们需要先创建 /etc/docker/daemon.json 文件:

$ sudo touch /etc/docker/daemon.json

然后编辑其内容如下(如果该文件已经存在,仅添加下面的配置项即可),并重启 docker 服务:

{   "userns-remap": "default" }$ sudo systemctl restart docker.service

下面我们来验证几个关于用户隔离的几个点。

首先验证 docker 创建了一个名为 dockremap 的用户:

然后查看 /etc/subuid 和 /etc/subgid 文件中是否添加了新用户 dockremap 相关的项:

接下来我们发现在 /var/lib/docker 目录下新建了一个目录: 165536.165536,查看该目录的权限:

165536 是由用户 dockremap 映射出来的一个 uid。查看 165536.165536 目录的内容:

与  /var/lib/docker 目录下的内容基本一致,说明启用用户隔离后文件相关的内容都会放在新建的 165536.165536 目录下。

通过上面的检查,我们可以确认 docker daemon 已经启用了用户隔离的功能。

宿主机中的 uid 与容器中 uid

在 docker daemon 启用了用户隔离的功能后,让我们看看宿主机中的 uid 与容器中 uid 的变化。

$ docker run -d --name sleepme ubuntu sleep infinity

uid 165536 是用户 dockremap 的一个从属 ID,在宿主机中并没有什么特殊权限。然而容器中的用户却是 root,这样的结果看上去很完美:

新创建的容器会创建 user namespace

在 docker daemon 启用用户隔离的功能前,新创建的容器进程和宿主机上的进程在相同的 user namespace 中。也就是说 docker 并没有为容器创建新的 user namespace:

上图中的容器进程 sleep 和宿主机上的进程在相同的 user namespace 中(没有开启用户隔离功能的场景)。

在 docker daemon 启用用户隔离的功能后,让我们查看容器中进程的 user namespace:

上图中的 4404 就是我们刚启动的容器中 sleep 进程的 PID。可以看出,docker 为容器创建了新的 user namespace。在这个 user namespace 中,容器中的用户 root 就是天神,拥有至高无上的权力!

访问数据卷中的文件

我们可以通过访问数据卷中的文件来证明容器中 root 用户究竟具有什么样的权限?创建四个文件,分别属于用户 root 、165536 和 nick。rootfile 只有 root 用户可以读写,用户 nick 具有 nickfile 的读写权限,uid 165536 具有文件 165536file 的读写权限,任何用户都可以读写 testfile 文件:

下面把这几个文件以数据卷的方式挂载到容器中,并检查从容器中访问它们的权限:

$ docker run -it --name test -w=/testv -v $(pwd)/testv:/testv ubuntu

容器中的 root 用户只能访问 165536file 和 testfile,说明这个用户在宿主机中只有非常有限的权限。

在容器中禁用 user namespace

一旦为 docker daemon 设置了 "userns-remap" 参数,所有的容器默认都会启用用户隔离的功能(默认创建一个新的 user namespace)。有些情况下我们可能需要回到没有开启用户隔离的场景,这时可以通过 --userns=host 参数为单个的容器禁用用户隔离功能。--userns=host 参数主要给下面三个命令使用:

docker container create docker container run docker container exec

比如执行下的命令:

$ docker run -d --userns=host --name sleepme ubuntu sleep infinity

查看进程信息:

进程的有效用户又成 root 了,并且也没有为进程创建新的 user namespace:

已知问题

User namespace 属于比较高级的功能,目前 docker 对它的支持还算不上完美,下面是已知的几个和现有功能不兼容的问题:

  • 共享主机的 PID 或 NET namespace(--pid=host or --network=host)
  • 外部的存储、数据卷驱动可能不兼容、不支持 user namespace
  • 使用 --privileged 而不指定 --userns=host

总结

Docker 是支持 user namespace 的,并且配置的方式也非常简便。在开启 user namespace 之后我们享受到了安全性的提升,但同时也会因为种种限制让其它的个别功能出现问题。这时我们需要作出选择,告别一刀切的决策,让合适的功能出现的合适的场景中。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
“在配置 docker daemon 启用 user namespace 前,我需要先来了解一些关于从属(subordinate)用户/组和映射(remapping)的概念。从属用户和组的映射由两个配置文件来控制,分别是 /etc/subuid 和 /etc/subgid。看下它们的默认内容:在配置 docker daemon 启用 user namespace 前,我需要先来了解一些关于从属(subordinate)用户/组和映射(remapping)的概念 ”这段话重复了
“在配置 docker daemon 启用 user namespace 前,我需要先来了解一些关于从属(subordinate)用户/组和映射(remapping)的概念。从属用户和组的映射由两个配置文件来控制,分别是 /etc/subuid 和 /etc/subgid。看下它们的默认内容:在配置 docker daemon 启用 user namespace 前,我需要先来了解一些关于从属(subordinate)用户/组和映射(remapping)的概念 ”这段话重复了
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
docker namespaces
https://docs.docker.com/engine/security/userns-remap/#prerequisites
charlieroro
2020/03/24
1.3K0
docker namespaces
docker 非root用户修改mount到容器的文件出现“Operation not permitted
进入容器,在/mnt目录下进行修改文件属性的操作,出现如下错误(此时容器中的user id=0)
charlieroro
2020/03/24
5.2K0
Docker安全配置分析
容器技术基于容器主机操作系统的内核,通过对CPU、内存和文件系统等资源的隔离、划分和控制,实现进程之间透明的资源使用。因此,容器主机的安全性对整个容器环境的安全有着重要的影响。
绿盟科技研究通讯
2019/12/11
1.9K0
Docker安全配置分析
Docker的资源隔离(NameSpace)
Docker通过namespace(命名空间)实现资源隔离。Namespace是Linux系统提供的资源隔离机制,只有在同一个namespace下的进程可以互相联系,但无法感受外部进程的存在,从而实现资源隔离。
空洞的盒子
2024/02/28
5421
如何在Rootless模式下运行Docker
告别sudo!无需Root权限也能玩转Docker?本文教你如何在无Root模式下安装Docker,利用用户命名空间隔离权限,保障安全。但需注意端口限制和cgroup v2依赖。更有uidmap安装、NGINX测试等干货,更有Podman等替代方案,云原生安全再升级!
云云众生s
2025/03/20
1200
Docker Rootless 在非特权模式下运行 Docker
Rootless 模式允许以非 root 用户身份运行 Docker 守护进程(dockerd)和容器,以缓解 Docker 守护进程和容器运行时中潜在的漏洞。Rootless 模式是在 Docker v19.03 版本作为实验性功能引入的,在 Docker v20.10 版本 GA。
Se7en258
2021/12/31
7.7K0
Docker Rootless 在非特权模式下运行 Docker
说说linux容器的隔离
说到docker,大家都懂。但是LXC可能就比较陌生。Docker的起源于LXC。LXC的英文全称是Linux Container,相比较其他虚拟机而言,是一种轻量级虚拟化技术,它介于Chroot(linux的一个改变根目录挂载点的机制)和完整开发的虚拟机之间。LXC不使用单独的内核资源,但是可以创建一个类似的Linux操作系统环境。
mariolu
2020/02/13
3.2K0
千年的铁树开了花。聊聊account
account真是一个千年铁树,但神奇的是它又总是在开新花。从我使用电脑第一天起就需要记住账号,只有输对了账号密码才可以登录实验室那台Windows玩扫雷游戏。如今大红大紫的零信任里重要的组成部分IAM也在谈账号,零信任需要基于账号来回答一个灵魂拷问:谁,在何时,于何地,访问了何种服务,这样的访问行为是否经过授权?SASE是另外一个大火的概念,你看它的全称:Secure Access Service Edge,再一次提到了access,是的,基于Identity的access。
LanceZhang
2021/12/06
5530
千年的铁树开了花。聊聊account
Podman 保姆级使用教程,太顶了!
cockpit-podman 软件包作为 cockpit 插件可集成于 Web UI 中,实现 Web UI 管理容器。
米开朗基杨
2022/04/09
20.9K1
Podman 保姆级使用教程,太顶了!
Docker安全入门与实战(四)
众所周知,Docker使用namespace进行环境隔离、使用cgroup进行资源限制。但是在实际应用中,还是有很多企业或者组织没有使用namespace或者cgroup对容器加以限制,从而埋下安全隐患。本文定位于简单介绍namespace和cgroup的基本原理之后,通过具体配置和应用向读者展示如何应用这些技术保护docker容器安全,不过namespace和cgroup并不是万能的,他们只是保障Docker容器安全的多种方案中的一类而已。
0xtuhao
2022/06/21
3300
浅谈日常使用的 Docker 底层原理-三大底座
适合的读者,对Docker有过简单了解的朋友,想要进一步了解Docker容器的朋友。
宁在春
2023/10/16
1.5K0
浅谈日常使用的 Docker 底层原理-三大底座
【随笔小记】提高Docker容器的安全性
随着 Docker 的兴起,越来越多的项目采用 Docker 搭建生产环境,因为容器足够轻量化,可以快速启动并且迁移业务服务,不过在使用的过程中,我们很容易就忽略了项目的安全问题,容器虽然有隔离的作用,但是我们知道,他与虚拟机的架构差距还是比较大的。
Balliol Chen
2022/04/21
5650
Linux安装Docker并配置Docker镜像加速,daemon.json完整配置详解
修改配置文件/etc/docker/daemon.json,进入/etc/docker目录。查看是否有daemon.json文件,没有则执行如下命令创建。
共饮一杯无
2022/11/28
14.3K0
Linux安装Docker并配置Docker镜像加速,daemon.json完整配置详解
如何在主机上调试容器、在容器中操作主机
老板有个奇怪的需求,通过一个 kubeconfig 文件,获取主机的各种状态信息,比如进程列表、进程状态等。
陈少文
2021/01/13
2.5K1
如何在主机上调试容器、在容器中操作主机
Docker安全入门与实战(一)
与其他介绍Docker的文章不同,由本文开启的系列文章将专注于Docker安全研究,一共分为6部分。
0xtuhao
2022/06/21
1.1K0
Docker安全入门与实战(一)
最流行的容器运行时Podman,如何拿下17K Star?
Podman是一个基于libpod库开发的容器运行时,用于在Linux操作系统上管理和运行容器。与传统的Docker容器运行时不同,Podman无需依赖Docker守护进程,它可以在不同的Linux发行版中独立运行。
MCNU云原生
2023/03/17
9720
最流行的容器运行时Podman,如何拿下17K Star?
如何提升docker容器安全性
原创文章,转载请务必将下面这段话置于文章开头处。 本文转发自:字母哥博客,原文链接 http://www.zimug.com/463.html
字母哥博客
2020/09/23
1.1K0
rootless Podman如何工作?【Programming】
在上一篇有关用户名称空间和Podman的文章中,我讨论了如何使用Podman命令来启动具有不同用户名称空间的不同容器,从而更好地分隔容器。Podman还利用用户名称空间来以无根模式运行。基本上,当非特权用户运行Podman时,该工具将设置并加入用户名称空间。在Podman成为用户名称空间内的root用户后,允许Podman挂载某些文件系统并设置容器。请注意,除了用户可用的其他UID之外,此处没有特权升级,如下所述。
Potato
2019/11/24
2.3K0
rootless Podman如何工作?【Programming】
The Route to Host:从内核提权到容器逃逸
绿盟科技研究通讯曾经发表过容器逃逸的技术文章《【云原生攻防研究】容器逃逸技术概览》[1],该文中探讨了已有的容器逃逸技术。本文将沿着上文的思路,主要从Linux内核漏洞的角度对容器逃逸进行深度介绍,包括攻击原理、自动化利用和防御思路等内容。
绿盟科技研究通讯
2022/04/14
1.8K0
The Route to Host:从内核提权到容器逃逸
Docker
与其他介绍Docker的文章不同,由本文开启的系列文章将专注于Docker安全研究,一共分为6部分。
扬起
2022/06/24
1.2K0
Docker
相关推荐
docker namespaces
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文