文档章节

体验了一下Docker的root用户映射

Q_J
 Q_J
发布于 2016/06/24 22:09
字数 1402
阅读 402
收藏 1

###2016/07/01:要想限制容器里用户的权限,有两种方法:

  1. 让你在容器里做个凡人(这个方法对于有些需要root的容器是不适合的)

具体的就是,指定容器里用户的uid:gid,使得容器里压根不存在root用户。

$ docker run -it -u 1000:1000 ubuntu
groups: cannot find name for group ID 1000   #这个错误没关系
I have no name!@fcaadb40ddd0:/$ id     #执行id命令看看结果。
uid=1000 gid=1000 groups=1000

(这里的uid:gid和主机的不一样,具体的怎么关联的不太清楚。一般来说这个就足够了,但是也许会有什么应用需要root权限,这时就需要下一步要说的方法来限制权限了)

  1. 让你在容器里做玉皇大帝, 但是这个玉皇大帝和所有凡人,都只是被映射到茫茫宇宙中一片卑微甚至虚空的身份上

就算容器里有个孙悟空突破了限制做了玉皇大帝,那也翻不出如来佛的手掌。 具体的就是,把容器里的root等用户映射成主机那边的指定的一片uid:gid。


###2017/01/20:忽然想起来看看,容器里以root运行的进程,在外面看来到底是什么?是一个进程。那是什么用户身份呢?也是root,只是capabilities受到很多限制,理论上依然危险。

在docker里以root身份运行sleep 12345

docker@somehost:~$ docker run -it busybox
/ # id
uid=0(root) gid=0(root) groups=10(wheel)
/ # sleep 12345

在容器外面查看这个sleep是什么进程,什么用户身份?也是root。

docker@somehost:~$ ps -ef |grep 12345
root      1997  1980  0 09:44 pts/1    00:00:00 sleep 12345

查看该进程的权限信息,就能够发现capabilities是受限制的,但是理论上还是可以钻漏洞影响到容器外的。

docker@somehost:~$ cat /proc/1997/status |grep Cap
...
CapEff:	00000000a80425fb
...

用capsh工具查看00000000a80425fb就明白意思。这个root收到了限制。

最近用的docker-machine版本是0.8.2,docker 1.12.5。发现docker-machine里面已经默认创建好了dockremap这个用户了,连/etc/subuid /etc/subgid里都准备好了。结果,只要修改活着创建/etc/docker/daemon.json,加上{"userns-remap":"default"}就可以了,重启动docker-machine就可以生效。

确认

docker@somehost:~$ cat /etc/subuid 
dockremap:165536:65536
docker@somehost:~$ cat /etc/subgid 
dockremap:165536:65536

准备

docker@somehost:~$ cat /etc/docker/daemon.json
{
  "userns-remap": "default"
}

如果还不存在dockremap用户,那么就运行这个命令生成用户dockremap:

sudo adduser --system dockremap

重启动

docker-machine restart somehost
docker-machine ssh somehost

在docker里以root身份运行sleep 12345

docker@somehost:~$ docker run -it busybox
/ # id
uid=0(root) gid=0(root) groups=10(wheel)
/ # sleep 12345

在容器外面查看这个sleep是什么进程,什么用户身份

docker@somehost:~$ ps -ef |grep 12345
165536    2360  2344  0 09:36 ?        00:00:00 sleep 12345

就是这个165536,说明生效了,用户身份不是以前的0(root)了。


####2016/?/?: 我要体验的就是第2种功能,刚出来半年,因为uid映射只能手动做,而且是针对docker daemon设定的,所以默认是不开启的,也无法从普通的docker run命令里指定。

参照了docker-for-your-users-introducing-user-namespace

主要是docker daemon加个选项 --userns-remap=test_user:test_group and add /etc/subuid /etc/subgid

如果按照docker官方文档说的--userns-remap=default(就是让docker daemon创建dockremap用户),也会报错说找不到用户,据有的用户反映是tiny core linux里的adduser和普通的linux发行版不一样,我没仔细查。

$ docker-machine ssh rethink   # rethink is my vm name, please change it to yours.
...
docker@rethink:~$ sudo vi /var/lib/boot2docker/profile 
...
EXTRA_ARGS='
--label provider=virtualbox
--userns-remap=test_user:test_group            #####this is what i add#####
'
...
docker@rethink:~$ exit

then restart by docker-machine restart rethink, cause same error Maximum number of retries (10) exceeded (看/var/lib/boot2docker/docker.log能看到错误是说用户找不到), docker daemon is not started,

then add user/group,

docker@rethink:~$ sudo addgroup -g 20 test_group
docker@rethink:~$ sudo adduser -G test_group -SDHu 501 test_user

then prepare uid/gid range for container

docker@rethink:~$ sudo -c "echo test_user:100000:65536 > /etc/subuid"
docker@rethink:~$ sudo  -c "echo test_group:200000:65536 > /etc/subgid"

then start docker daemon

docker@rethink:~$ sudo /usr/local/bin/docker daemon -D -g "/var/lib/docker" -H unix:// -H tcp://0.0.0.0:2376 --label provider=virtualbox \
--userns-remap=test_user:test_group --tlsverify --tlscacert=/var/lib/boot2docker/ca.pem --tlscert=/var/lib/boot2docker/server.pem --tlskey=/var/lib/boot2docker/server-key.pem -s aufs

...
INFO[0000] User namespaces: ID ranges will be mapped to subuid/subgid ranges of: test_user:test_group 
DEBU[0000] Creating user namespaced daemon root: /mnt/sda1/var/lib/docker/100000.200000 
...

Then i run docker container. There are strange thing here: previously used docker image will be treated as "not exist", get downloaded again.

$ docker run -it -v /bin:/xxx busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
8ddc19f16526: Pull complete 
Digest: sha256:a59906e33509d14c036c8678d687bd4eec81ed7c4b8ce907b888c607f6a1e0e6
Status: Downloaded newer image for busybox:latest
/ # id
uid=0(root) gid=0(root) groups=10(wheel)
/ # ls /xxx
VBoxClient     cat            dd             echo           gunzip         ln             mount          printenv       ...
...
/ # echo hi > /xxx/a
sh: can't create /xxx/a: Permission denied

很好, container里的root只能老老实实的以host os里的test_user身份运行了。

不过一旦重启动就泡汤了(还是老错误说用户找不到), 出现问题后,请进去把/var/lib/boot2docker/profile里的改动给恢复就行了。

重启动导致的问题很好理解,八成是因为docker-machine的VM是从关盘(boot2docker.iso)里启动的,我做的修改大部分都是在iso的内存盘里做的,并没保存到iso里,这是docker-machine的一个问题,有人提了建议了。

© 著作权归作者所有

共有 人打赏支持
Q_J

Q_J

粉丝 12
博文 67
码字总数 54682
作品 0
日本
私信 提问
使用docker在CentOS7上搭建WordPress

自己课题组的网页挂了,老板一句话让我们自己写一个。结果被我拖了半年,结果丢给师弟,师弟决定用WordPress, 于是我就去给他配置服务器环境。 首先你得知道什么叫做WordPress, 它是一个基于...

徐洲更
2018/10/23
0
0
使用 Docker 的用户名字空间功能

用户名字空间User Namespaces 于 Docker 1.10 版本正式纳入其中,该功能允许主机系统将自身的 和 映射为容器进程中的另一个 和 。这对 Docker 的安全性来说是一项巨大的改进。下面我会通过一...

09%
2018/08/23
0
0
docker搞个wordpress

1.先把wordpress的镜像下载下来 2.下载mysql 3.启动mysql name参数指定要启动的实例名称这里我称mysql实例为some-mysql,MYSQLROOTPASSWORD指定ROOT密码。tag参数是MySQL的版本号,可以是5.7...

无极之岚
2018/12/13
0
0
可持续自动化构建微服务(4)Centos7 安装 docker

第四章 Centos7 安装 docker Docker 是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,...

jato333
2018/05/28
0
0
普通用户借助docker容器提权思路分享

  随着docker越来越流行,很多公司内部linux机器上docker成了标配。       免sudo使用docker   默认情况下使用docker必须要有sudo权限,对于一台机器多用户使用,往往很多用户只有普...

FreeBuf
2018/05/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Confluence 6 升级中的一些常见问题

升级的时候遇到了问题了吗? 如果你想尝试重新进行升级的话,你需要首先重新恢复老的备份。不要尝试再次对 Confluence 进行升级或者在升级失败后重新启动老的 Confluence。 在升级过程中的一...

honeymoose
47分钟前
2
0
C++随笔(四)Nuget打包

首先把自己编译好的包全部准备到一个文件夹 像这样 接下来新建一个文本文档,后缀名叫.nuspec 填写内容 <?xml version="1.0"?><package xmlns="http://schemas.microsoft.com/packaging/201......

Pulsar-V
今天
2
0
再谈使用开源软件搭建数据分析平台

三年前,我写了这篇博客使用开源软件快速搭建数据分析平台, 当时收到了许多的反馈,有50个点赞和300+的收藏。到现在我还能收到一些关于dataplay2的问题。在过去的三年,开源社区和新技术的发...

naughty
今天
3
0
Python3的日期和时间

python 中处理日期时间数据通常使用datetime和time库 因为这两个库中的一些功能有些重复,所以,首先我们来比较一下这两个库的区别,这可以帮助我们在适当的情况下时候合适的库。 在Python文...

编程老陆
今天
2
0
分布式面试整理

并发和并行 并行是两个任务同时进行,而并发呢,则是一会做一个任务一会又切换做另一个任务。 临界区 临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用,但是每一次,只能有...

群星纪元
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部