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