尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Podman podmansh 完全指南:用 Quadlet 容器把登录 Shell 锁进沙箱

Podman podmansh 完全指南:用 Quadlet 容器把登录 Shell 锁进沙箱 容器运行时云原生CLI【免费下载链接】podmanPodman: A tool for managing OCI containers and pods.项目地址https://gitcode.com/gh_mirrors/po/podman点击查看免费下载podmansh 是 Podman 提供的一种登录 Shell 即容器机制把用户系统登录后的 Shell 直接放进一个由管理员预定义的 Quadlet 容器中执行用户全程只能接触容器内环境与显式挂载的卷。本文基于仓库中 podmansh.1.md 文档结合源码、Quadlet 单元格式与 containers.conf 配置讲解从用户创建、Quadlet 编写到三种安全档位完全锁定 / 挂载家目录 / 嵌套容器的完整落地过程。podmansh 是什么把系统登录 Shell 搬进容器传统做法中管理员限制用户往往依靠 chroot、受限 Shell 或 SELinux 策略。podmansh 换了一种思路用户的登录 Shell 直接就是/usr/bin/podmansh当用户通过 SSH、控制台等方式登录时systemd 先为其启动一个名为podmansh的 Quadlet 容器然后用户的 Shell 在这个容器内部被自动执行。从文档描述podmansh.1.md可以提炼出几个关键事实用户归属由 Quadlet 决定用户被加入哪个容器由管理员在/etc/containers/systemd/users下放置的 Quadlet 文件定义。安全边界明确用户只能访问该 Quadlet 中显式配置的卷和能力capabilities并通过包括 SELinux 在内的全部安全机制被限制在容器环境内用户能接触到的宿主机信息仅来源于被泄露进容器的卷。生命周期自动管理systemd 在用户会话启动时自动创建容器在所有连接到该用户会话的连接都被移除后自动拆除容器因此用户可多次登录系统每次会话都连接到同一个容器。可配置超时可通过 containers.conf 中的podmansh_timeout选项设置 podmansh 的超时时间。值得说明的是podmansh 并非常规的交互式命令工具而是作为登录 Shell 存在。仓库源码也印证了这一点在 cmd/podman/registry/remote.go 中定义了const PodmanSh podmansh并且isRemote判断会特殊处理 podmansh——当命令行第一个参数是 podmansh 时强制保持本地模式原因是 remote 模式与 podmansh 在-c参数的解析上存在冲突例如用户通过ssh userhost id执行命令时-c会被误解析。对应的单元测试 TestIsRemotePodmanSh 明确断言期望 podmansh 保持本地执行这从源码层面证实了 podmansh 是本地、容器内执行的设计。前置条件与总体架构依赖组件podmansh 依赖以下组件协同工作组件作用Podman Quadlet用声明式的.container单元文件定义 podmansh 容器systemd 按需启动/停止systemd用户级在/etc/containers/systemd/users下解析 Quadlet 并管理容器生命周期/usr/bin/podmansh作为用户登录 Shell 的可执行入口containers.conf可选的podmansh_timeout超时配置目录与文件布局管理员创建 Quadlet 有两个层级全局用户级放在/etc/containers/systemd/users/systemd 会在所有用户登录时为其启动这些服务。单用户级放在/etc/containers/systemd/users/${UID}/目录只有该 UID 的用户登录时才执行其中的 Quadlet 服务。两种方式都必须遵循一条硬性要求容器的名称必须为podmanshQuadlet 中ContainerNamepodmansh这是 podmansh 会话加入容器的前提。生命周期systemd 会在用户会话启动时自动创建容器当所有连接到该用户会话的连接如所有 SSH 会话都被移除后systemd 自动将容器拆除。因此多终端登录共享同一容器会话结束自动回收资源均由 systemd 处理无需管理员额外编写清理脚本。快速上手创建锁定的登录用户以下操作均在 root 下执行。第一步用useradd创建一个登录 Shell 为/usr/bin/podmansh的用户# useradd -s /usr/bin/podmansh lockedu # grep lockedu /etc/passwd lockedu:x:4008:4008::/home/lockedu:/usr/bin/podmansh第二步为该用户按 UID创建专属 Quadlet 目录并写入容器单元文件。注意其中的%h、${UID}等占位符与 shell 变量展开USERID$(id -u lockedu)取得用户 UID 后用于构造目录路径_EOF用于防止 heredoc 中的变量被提前展开。# USERID$(id -u lockedu) # mkdir -p /etc/containers/systemd/users/${USERID} # cat /etc/containers/systemd/users/${USERID}/podmansh.container _EOF [Unit] DescriptionThe podmansh container Afterlocal-fs.target [Container] Imageregistry.fedoraproject.org/fedora ContainerNamepodmansh UserNSkeep-id RunInityes DropCapabilityall NoNewPrivilegestrue Execsleep infinity [Install] RequiredBydefault.target _EOF该示例呈现的是完全锁定的配置容器不挂载任何卷、丢弃全部 Linux capabilities、禁止提升权限用户只能在一个与宿主机隔离的容器内使用。用户此后通过 SSH 登录时得到的即是一个受限的容器 Shell。三个实战档位的 Quadlet 配置详解文档给出了三种从严到宽的配置范例下面逐一展开说明每个关键参数的实际含义。档位一完全锁定无卷、无特权即上文示例。核心参数含义如下UserNSkeep-id使用用户命名空间并将容器内用户映射到与宿主机相同的 UID/GID用户在容器内的身份与宿主机登录身份一致对应podman run --usernskeep-id。RunInityes容器内以 init 进程tini 等作为 PID 1负责回收孤儿进程与转发信号对应podman run --init。DropCapabilityall丢弃容器可用的全部 capabilities容器内进程不再拥有任何特权能力对应--cap-dropall。NoNewPrivilegestrue禁止容器内进程通过 setuid/setgid 等方式获得新特权对应--security-opt no-new-privileges。Execsleep infinity容器主进程为长驻的sleep保证容器在用户会话期间始终处于运行状态供登录 Shell 加入。参数与podman run的对应关系可进一步参考 podman-systemd.unit.5.md 中 Quadlet 单元指令对照表如UserNS、RunInit、DropCapability、NoNewPrivileges等行。档位二允许容器内提权 卷挂载家目录如果希望用户在容器内可以成为 root处于用户命名空间内并且其家目录数据持久保存在宿主机真实账户目录而非容器内可以使用带卷挂载的配置# useradd -s /usr/bin/podmansh confinedu # grep confinedu /etc/passwd confinedu:x:4009:4009::/home/confinedu:/usr/bin/podmansh # USERID$(id -u confinedu) # mkdir -p /etc/containers/systemd/users/${USERID} # cat /etc/containers/systemd/users/${USERID}/podmansh.container _EOF [Unit] DescriptionThe podmansh container Afterlocal-fs.target [Container] Imageregistry.fedoraproject.org/fedora ContainerNamepodmansh UserNSkeep-id RunInityes Volume%h/data:%h:Z Execsleep infinity [Service] ExecStartPre/usr/bin/mkdir -p %h/data [Install] RequiredBydefault.target _EOF与档位一的区别集中在两点去掉了DropCapabilityall与NoNewPrivilegestrue因此用户命名空间内的该用户可以成为容器内 root。增加了卷与目录准备Volume%h/data:%h:Z把宿主机家目录下的data子目录以:Z自动重打 SELinux 标签挂载进容器[Service]段的ExecStartPre/usr/bin/mkdir -p %h/data在容器启动前确保宿主机目录存在否则挂载会失败。%h是 systemd 对用户主目录的占位符。档位三允许嵌套运行容器并启用 SELinux 分离如果希望容器内用户还能再执行容器嵌套容器场景且保留 SELinux 安全隔离可使用PodmanArgs注入额外的安全选项# useradd -s /usr/bin/podmansh fullu # grep fullu /etc/passwd fullu:x:4010:4010::/home/fullu:/usr/bin/podmansh # USERID$(id -u fullu) # mkdir -p /etc/containers/systemd/users/${USERID} # cat /etc/containers/systemd/users/${USERID}/podmansh.container _EOF [Unit] DescriptionThe podmansh container Afterlocal-fs.target [Container] Imageregistry.fedoraproject.org/fedora ContainerNamepodmansh UserNSkeep-id RunInityes PodmanArgs--security-optunmask/sys/fs/selinux \ --security-optlabelnested \ --security-optlabeluser:container_user_u \ --security-optlabeltype:container_user_t \ --security-optlabelrole:container_user_r \ --security-optlabellevel:s0-s0:c0.c1023 Volume%h/data:%h:Z WorkingDir%h Volume/sys/fs/selinux:/sys/fs/selinux Execsleep infinity [Service] ExecStartPre/usr/bin/mkdir -p %h/data [Install] RequiredBydefault.target _EOF该档位的要点PodmanArgs向podman run追加任意参数对应 podman-systemd.unit.5.md 中的PodmanArgs指令。这里注入的--security-opt包括unmask/sys/fs/selinux解除对 SELinux 文件系统的屏蔽、labelnested允许嵌套容器标签、以及labeluser/type/role/level为容器指定 SELinux 用户container_user_u、类型container_user_t、角色container_user_r与 MLS 级别s0-s0:c0.c1023。WorkingDir%h将容器内工作目录设为用户家目录对应--workdir。第二个Volume/sys/fs/selinux:/sys/fs/selinux把宿主机的 SELinux 文件系统挂载进容器使容器内能够执行需要 SELinux 支撑的嵌套容器操作。三个档位覆盖了纯隔离 → 家目录持久化 → 嵌套容器的递进需求管理员可按安全策略选择。所有示例中ContainerNamepodmansh都必须保持不变。超时与 containers.conf 配置podmansh 的登录超时可通过 containers.conf 的podmansh_timeout选项设置。在当前仓库中该配置项的实际实现位于 vendored 的 common 配置包config.go其中定义了PodmanshConfig结构体Shell容器内启动的 Shell默认/bin/sh对应[podmansh] shell配置项。Containerpodmansh 用户应加入的容器名默认podmansh对应[podmansh] container配置项。Timeout等待 podmansh 登录的秒数即等待podmansh容器进入 running 状态的超时对应[podmansh] timeout配置项。默认配置模板 containers.conf 中给出了[podmansh]段落的说明[podmansh] # Shell to spawn in container. Default: /bin/sh. #shell /bin/sh # # Name of the container the podmansh user should join. #container podmansh # # Default timeout in seconds for podmansh logins. # Favored over the deprecated podmansh_timeout field. #timeout 30从模板注释可以看出文档中提到的podmansh_timeout引擎级字段见 config.go 中的PodmanshTimeout uint \toml:podmansh_timeout,omitempty,omitzero属于**已弃用**字段当前仓库中Config.PodmanshTimeout()方法会优先返回[podmansh] timeout新字段未设置时才回退到引擎级的podmansh_timeout 以保持向后兼容见 config.go 的相关实现。[podmansh] timeout默认值为 30 秒语义是等待 podmansh 容器进入 running 状态的超时。常见问题与最佳实践为什么必须叫podmansh容器podmansh 会话会加入名为podmansh的容器因此 Quadlet 中必须写ContainerNamepodmansh这也是为什么[podmansh] container配置项的默认值就是podmansh。改容器名会导致登录会话无法加入容器。用户家目录数据去哪了默认情况下不挂卷容器内的家目录只是镜像内的临时数据用户的一切写入在容器销毁后即丢失只有显式通过Volume挂载如档位二的%h/data:%h:Z才能持久化到宿主机。安全基线建议最低权限原则不需要提权时保留DropCapabilityall与NoNewPrivilegestrue。只挂载必要目录通过卷泄露给用户的宿主机数据越少越好这正是文档强调的用户只能看到被泄露进容器的卷的安全模型。需要嵌套容器时务必理解labelnested与 SELinux 挂载带来的额外攻击面并按需缩小 MLS 级别范围。配置改动后需重新加载 systemd 用户单元systemctl --user daemon-reload或在对应 UID 下执行使 Quadlet 生效实际生效方式以系统 systemd 版本与部署方式为准。与 remote 模式的兼容性从源码看podmansh 被设计为本地执行的登录 ShellIsRemote()在检测到命令行首参数为 podmansh 时会强制返回本地模式避免-c参数在 remote 解析中出错remote.go。因此不要在 podmansh 用户的登录场景中依赖 remote/隧道模式。参考文档podmansh.1.md本指南依据的原始手册页NAME / SYNOPSIS / DESCRIPTION / Setup / SEE ALSO / HISTORYcontainers.conf(5)containers.conf 配置手册含podmansh_timeout选项说明podman(1)podman 主命令手册podman-exec(1)进入运行中容器执行命令podman-systemd.unit(5)Quadlet 单元格式手册UserNS、RunInit、DropCapability、NoNewPrivileges、PodmanArgs、WorkingDir等指令vendor/go.podman.io/common/pkg/config/config.goPodmanshConfig与PodmanshTimeout实现vendor/go.podman.io/common/pkg/config/containers.conf[podmansh]段默认配置模板cmd/podman/registry/remote.gopodmansh 本地模式检测逻辑赞分享容器运行时云原生CLI【免费下载链接】podmanPodman: A tool for managing OCI containers and pods.项目地址https://gitcode.com/gh_mirrors/po/podman点击查看免费下载相关推荐Podman Quadlet 列表过滤指南podman quadlet list --filter 完全解读Podman Quadlet 列表过滤指南 podman quadlet list filter 完全解读 podman quadlet list filte容器运行时云原生CLIcpp-httplib三分钟跑起来的单文件 C HTTP/HTTPS 库cpp httplib三分钟跑起来的单文件 C HTTP/HTTPS 库 cpp httplib 是一个 C11 单文件 HTTP/HTTPS 库整容器运行时云原生CLIOmniRoute Podman 部署实战Quadlet 与 podman compose 双路径完全指南OmniRoute Podman 部署实战Quadlet 与 podman compose 双路径完全指南 OmniRoute 作为一套自带 Web 仪表盘、LLM 网关人工智能API网关后端前端桌面应用上一篇告别Naive UI报错困扰从表单验证到组件调试的全流程解决方案下一篇革命性Android热修复方案Aceso基于Instant Run技术实时修复线上Bug无需重启创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表