有没有非 root 用户下,能创建出一个隔离 rootfs 内的交互式 shell 的轮子

2023-10-12 19:34:20 +08:00
 guanzhangzhang

比如 test01 执行个轮子后,进入了一个隔离的 chroot 类似。

主要是 web 上点击提供一个 web shell 类似,里面的 rootfs 带了 kubectl ,目前同事用 webkubectl 项目使用,但是前不久客户让改为非 root 启动。大致看了下它的实现

  1. 特权容器内 root 用户执行 gotty 启动 start-session.sh 作为 pid 为 1 的角色
  2. 每次访问 web 就是执行 start-session.sh 的内容
    1. unshare --fork --pid --mount-proc --mount xxx.sh 启动隔离空间
    2. mkdir -p /nonexistent ,mount -t tmpfs -o size=${SESSION_STORAGE_SIZE} tmpfs /nonexistent 和一系列处理文件
    3. exec su nobody bash

然后改为非 root 启动 gotty 后,没有执行 unshare 和 mount 权限,所以来问下有没有什么轮子,非 root 用户执行,能 chroot 到一个小巧的 rootfs 内的 shell 交互(该 shell 内什么用户都行,对 chroot 之前的无影响)。目前试过 proot ,容器内 root 都无法启动

2710 次点击
所在节点    Linux
29 条回复
vcn8yjOogEL
2023-10-12 19:38:18 +08:00
podman?
codehz
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 应该就可以用了
ysc3839
2023-10-12 21:30:13 +08:00
直接用 Docker ?不过 docker daemon 也是要 root 的。这类系统级的功能估计都很难绕开 root ,真要搞的话只能依靠一些复杂的用户模式沙盒/虚拟化来实现了。
huahsiung
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 当轻量容器我用很久了
deorth
2023-10-12 23:26:25 +08:00
proot
wizardyhnr
2023-10-13 06:29:54 +08:00
@ysc3839 docker 有 rootless 的模式
guanzhangzhang
2023-10-13 09:24:39 +08:00
@codehz 大佬,咨询下,你说的情况在非 root 用户下,unshare 参数是多少😘
guanzhangzhang
2023-10-13 09:29:02 +08:00
@huahsiung 难道是我下载的 proot 不对吗,我是在 https://github.com/proot-me/proot-static-build 下载的
codehz
2023-10-13 09:58:58 +08:00
@guanzhangzhang unshare --fork --pid --map-root-user --mount-proc --propagation slave --setgroups deny
里面直接 mount/chroot 都没问题
codehz
2023-10-13 10:00:36 +08:00
哦,不要加 setgroups
ysc3839
2023-10-13 10:06:51 +08:00
@wizardyhnr 那不就完美解决楼主的问题了?程序自带一个 Docker 即可。
guanzhangzhang
2023-10-13 10:11:10 +08:00
@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
```
codehz
2023-10-13 10:15:18 +08:00
@guanzhangzhang 生活小技巧
在/tmp 上再挂一层 tmpfs ,然后把其他目录 bind mount 进去,接着 chroot 进/tmp ,然后再执行 mkdir 一类的操作
codehz
2023-10-13 10:20:37 +08:00
此外你可以选择先切到 nobody 再执行上面说的 unshare ,因为在 map-root-user 的模式下,没有办法再切别的用户了
codehz
2023-10-13 10:21:35 +08:00
仔细想你这只是为了家目录可写入的话,可以简单的直接在 unshare 里面 mount -t tmpfs tmpfs /root ,这样/root 就是可写入的家目录了
guanzhangzhang
2023-10-13 11:25:41 +08:00
@codehz #14 😢我发现容器内非 root 用户执行 unshare 的时候不能带--pid ,否则 unshare: unshare(0x20000000): Operation not permitted
codehz
2023-10-13 11:28:15 +08:00
pid namespace 好像问题不大,主要是方便一键咔掉子进程,这个可以用原用户开()
guanzhangzhang
2023-10-13 11:29:07 +08:00
@huahsiung 我发现 proot 能杀掉父进程,有隔离进程的吗,容器内非 root 执行 unshare 不能带--pid 的隔离
guanzhangzhang
2023-10-13 11:30:52 +08:00
@codehz #17 大佬,没看懂这个怎么搞
codehz
2023-10-13 11:38:55 +08:00
@guanzhangzhang 就是先用容器内的 root ,unshare --fork --pid
然后里面再 su nobody unshare ...

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/981439

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX