
比如 test01 执行个轮子后,进入了一个隔离的 chroot 类似。
主要是 web 上点击提供一个 web shell 类似,里面的 rootfs 带了 kubectl ,目前同事用 webkubectl 项目使用,但是前不久客户让改为非 root 启动。大致看了下它的实现
然后改为非 root 启动 gotty 后,没有执行 unshare 和 mount 权限,所以来问下有没有什么轮子,非 root 用户执行,能 chroot 到一个小巧的 rootfs 内的 shell 交互(该 shell 内什么用户都行,对 chroot 之前的无影响)。目前试过 proot ,容器内 root 都无法启动
1 vcn8yjOogEL 2023 年 10 月 12 日 podman? |
2 codehz 2023 年 10 月 12 日 你都 unshare 了,不如再 map-root-user 一下(也就是用 user namespace ) 不过你这个“小巧的 rootfs 内的 shell 交互”真的可以在非特权用户下跑吗? 你这个 rootfs 要可变的还是不可变的呢 不可变的话,我这有一个封装 rootfs 的小工具 https://github.com/codehz/EasyPak ,本来是用于快速封装一个二进制及其依赖到单文件 只是单纯 chroot 的话,unshare 的 map-root-user 应该就可以用了 |
3 ysc3839 2023 年 10 月 12 日 via Android 直接用 Docker ?不过 docker daemon 也是要 root 的。这类系统级的功能估计都很难绕开 root ,真要搞的话只能依靠一些复杂的用户模式沙盒/虚拟化来实现了。 |
4 huahsiung 2023 年 10 月 12 日 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 2023 年 10 月 12 日 via Android proot |
6 wizardyhnr 2023 年 10 月 13 日 @ysc3839 docker 有 rootless 的模式 |
7 guanzhangzhang OP @codehz 大佬,咨询下,你说的情况在非 root 用户下,unshare 参数是多少 |
8 guanzhangzhang OP @huahsiung 难道是我下载的 proot 不对吗,我是在 https://github.com/proot-me/proot-static-build 下载的 |
9 codehz 2023 年 10 月 13 日 @guanzhangzhang unshare --fork --pid --map-root-user --mount-proc --propagation slave --setgroups deny 里面直接 mount/chroot 都没问题 |
10 codehz 2023 年 10 月 13 日 哦,不要加 setgroups |
11 ysc3839 2023 年 10 月 13 日 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 2023 年 10 月 13 日 @guanzhangzhang 生活小技巧 在/tmp 上再挂一层 tmpfs ,然后把其他目录 bind mount 进去,接着 chroot 进/tmp ,然后再执行 mkdir 一类的操作 |
14 codehz 2023 年 10 月 13 日 此外你可以选择先切到 nobody 再执行上面说的 unshare ,因为在 map-root-user 的模式下,没有办法再切别的用户了 |
15 codehz 2023 年 10 月 13 日 仔细想你这只是为了家目录可写入的话,可以简单的直接在 unshare 里面 mount -t tmpfs tmpfs /root ,这样/root 就是可写入的家目录了 |
16 guanzhangzhang OP @codehz #14 我发现容器内非 root 用户执行 unshare 的时候不能带--pid ,否则 unshare: unshare(0x20000000): Operation not permitted |
17 codehz 2023 年 10 月 13 日 pid namespace 好像问题不大,主要是方便一键咔掉子进程,这个可以用原用户开() |
18 guanzhangzhang OP @huahsiung 我发现 proot 能杀掉父进程,有隔离进程的吗,容器内非 root 执行 unshare 不能带--pid 的隔离 |
19 guanzhangzhang OP @codehz #17 大佬,没看懂这个怎么搞 |
20 codehz 2023 年 10 月 13 日 @guanzhangzhang 就是先用容器内的 root ,unshare --fork --pid 然后里面再 su nobody unshare ... |
21 huahsiung 2023 年 10 月 13 日 @guanzhangzhang proot 不要下 static 编译的版本,可以直接从 apt 源安装。static 版本不依赖 so 库,trace 注入就有毛病。 static 版本有一些 bug 。不是静态版本的 proot ,如果杀掉父进程,子进程会被一起杀掉。 |
22 huahsiung 2023 年 10 月 13 日 没注意到这句话"容器内 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 2023 年 10 月 13 日 @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 2023 年 10 月 13 日 @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 2023 年 10 月 13 日 看看我的文章满足你的需求吗 blog.fansluck.top/non-root-container-guide.html |
28 guanzhangzhang OP @62742a40 不是。。。你这只适用于简单的命令和单个二进制启动 |
29 Jirajine 2023 年 10 月 13 日 via Android 你直接起 rootless container 不就完了,不需要自己手动 unshare 。 单应用 oci 镜像就用 podman ,系统镜像自己管理 rootfs 用 lxc 。 |