比如 test01 执行个轮子后,进入了一个隔离的 chroot 类似。
主要是 web 上点击提供一个 web shell 类似,里面的 rootfs 带了 kubectl ,目前同事用 webkubectl 项目使用,但是前不久客户让改为非 root 启动。大致看了下它的实现
然后改为非 root 启动 gotty 后,没有执行 unshare 和 mount 权限,所以来问下有没有什么轮子,非 root 用户执行,能 chroot 到一个小巧的 rootfs 内的 shell 交互(该 shell 内什么用户都行,对 chroot 之前的无影响)。目前试过 proot ,容器内 root 都无法启动
1
vcn8yjOogEL 229 天前
podman?
|
![]() |
2
codehz 229 天前
你都 unshare 了,不如再 map-root-user 一下(也就是用 user namespace )
不过你这个“小巧的 rootfs 内的 shell 交互”真的可以在非特权用户下跑吗? 你这个 rootfs 要可变的还是不可变的呢 不可变的话,我这有一个封装 rootfs 的小工具 https://github.com/codehz/EasyPak ,本来是用于快速封装一个二进制及其依赖到单文件 只是单纯 chroot 的话,unshare 的 map-root-user 应该就可以用了 |
![]() |
3
ysc3839 229 天前 via Android
直接用 Docker ?不过 docker daemon 也是要 root 的。这类系统级的功能估计都很难绕开 root ,真要搞的话只能依靠一些复杂的用户模式沙盒/虚拟化来实现了。
|
4
huahsiung 229 天前
proot 行啊。假如 rootfs 根目录为/home/user0/rootfs 。直接 proot -S /home/user0/rootfs /bin/bash 就进入容器内的 bash 了。
你试试 ```bash ~$:whoami user0 ~$:proot -S /home/user0/rootfs /bin/bash ~$:whoami root ``` 用 proot 当轻量容器我用很久了 |
5
deorth 229 天前 via Android
proot
|
6
wizardyhnr 229 天前
@ysc3839 docker 有 rootless 的模式
|
![]() |
7
guanzhangzhang OP @codehz 大佬,咨询下,你说的情况在非 root 用户下,unshare 参数是多少😘
|
![]() |
8
guanzhangzhang OP @huahsiung 难道是我下载的 proot 不对吗,我是在 https://github.com/proot-me/proot-static-build 下载的
|
![]() |
9
codehz 229 天前
@guanzhangzhang unshare --fork --pid --map-root-user --mount-proc --propagation slave --setgroups deny
里面直接 mount/chroot 都没问题 |
![]() |
10
codehz 229 天前
哦,不要加 setgroups
|
![]() |
11
ysc3839 229 天前 via Android
@wizardyhnr 那不就完美解决楼主的问题了?程序自带一个 Docker 即可。
|
![]() |
12
guanzhangzhang OP @codehz #10 大佬,map-root-user 后无法给结尾 nobody 需要的家目录,而且看似乎是--mount 配合形成 webkubectl 的 shell 隔离的
``` guanzhang@guan:~$ unshare --fork --pid --map-root-user --mount-proc --propagation slave bash root@guan:~# mkdir -p /nonexistent mkdir: cannot create directory ‘/nonexistent’: Permission denied ``` |
![]() |
13
codehz 229 天前
@guanzhangzhang 生活小技巧
在/tmp 上再挂一层 tmpfs ,然后把其他目录 bind mount 进去,接着 chroot 进/tmp ,然后再执行 mkdir 一类的操作 |
![]() |
14
codehz 229 天前
此外你可以选择先切到 nobody 再执行上面说的 unshare ,因为在 map-root-user 的模式下,没有办法再切别的用户了
|
![]() |
15
codehz 229 天前
仔细想你这只是为了家目录可写入的话,可以简单的直接在 unshare 里面 mount -t tmpfs tmpfs /root ,这样/root 就是可写入的家目录了
|
![]() |
16
guanzhangzhang OP @codehz #14 😢我发现容器内非 root 用户执行 unshare 的时候不能带--pid ,否则 unshare: unshare(0x20000000): Operation not permitted
|
![]() |
17
codehz 229 天前
pid namespace 好像问题不大,主要是方便一键咔掉子进程,这个可以用原用户开()
|
![]() |
18
guanzhangzhang OP @huahsiung 我发现 proot 能杀掉父进程,有隔离进程的吗,容器内非 root 执行 unshare 不能带--pid 的隔离
|
![]() |
19
guanzhangzhang OP @codehz #17 大佬,没看懂这个怎么搞
|
![]() |
20
codehz 229 天前
@guanzhangzhang 就是先用容器内的 root ,unshare --fork --pid
然后里面再 su nobody unshare ... |
21
huahsiung 229 天前
@guanzhangzhang proot 不要下 static 编译的版本,可以直接从 apt 源安装。static 版本不依赖 so 库,trace 注入就有毛病。
static 版本有一些 bug 。不是静态版本的 proot ,如果杀掉父进程,子进程会被一起杀掉。 |
22
huahsiung 229 天前
没注意到这句话"容器内 root 用户执行 gotty 启动 start-session.sh 作为 pid 为 1 的角色",然后再 unshare ??
原来已经是在容器中了?? 容器中是已经 chroot 的环境了,在 chroot 下,unshare 会有点问题。chroot 是这样的,可以看看 pivot_root |
![]() |
23
guanzhangzhang OP |
![]() |
24
guanzhangzhang OP @codehz #20 看了下逻辑流程不行,主要是非 root 的 gotty 执行脚本创建环境,如果 entrypoint.sh 隔离 pid ,然后内部 gotty 和最终的都是同一个 pid namespace ,😘,不过我们不用一个 webkubectl 操作多个 k8s ,不隔离也行。我去折腾下 proot
|
![]() |
25
codehz 229 天前
@guanzhangzhang 哦,也不是完全不行
我就整了一个 https://github.com/codehz/nobodyexec 编译好之后, unshare --pid --mount-proc --fork --propagation slave ./nobodyexec unshare --map-root-user bash start-session.sh 在 start-session.sh 现在就是 pid 1 的位置了 |
26
huahsiung 229 天前
@guanzhangzhang 看看/nonexistent/test 是完整的 rootfs ,并且/nonexistent/test/bin/sh 的依赖存在(/nonexistent/test/etc,/nonexistent/test/usr 等等),另外你可以试试 static 版本的 bash 。
http://ftp.debian.org/debian/pool/main/b/bash/bash-static_5.2.15-2+b2_amd64.deb |
27
62742a40 229 天前
看看我的文章满足你的需求吗
blog.fansluck.top/non-root-container-guide.html |
![]() |
28
guanzhangzhang OP @62742a40 不是。。。你这只适用于简单的命令和单个二进制启动
|
29
Jirajine 229 天前 via Android
你直接起 rootless container 不就完了,不需要自己手动 unshare 。
单应用 oci 镜像就用 podman ,系统镜像自己管理 rootfs 用 lxc 。 |