子UID空间是容器级用户隔离核心机制,通过/etc/subuid和/etc/subgid为租户分配不重叠ID范围(如tenant-a:100000:65536),配合userns-remap启用命名空间,并结合ACL与目录权限强化租户边界。

多租户环境下,子UID空间(subuid)是实现容器级用户隔离的核心机制。它让宿主机上的普通用户,在容器内部“看起来”是root,却只拥有宿主机上受限的权限,从根源上阻断权限提升攻击。
配置 /etc/subuid 和 /etc/subgid 映射
子UID/GID映射由两个系统文件控制,必须为每个租户用户显式分配一段独立、不重叠的ID范围:
- 编辑 /etc/subuid:每行格式为
用户名:起始子UID:ID数量,例如:tenant-a:100000:65536tenant-b:165536:65536 - 同步编辑 /etc/subgid:内容结构完全一致,仅将UID替换为GID,确保用户组映射对齐
- 分配原则:每个租户至少保留65536个连续ID(典型值),避免跨租户重叠;起始值建议从100000开始,避开系统保留范围(0–99999)
启用 user namespace 并验证映射生效
仅配置 subuid 文件还不够,需确保容器运行时真正启用 user namespace 隔离:
- 对于Docker:修改
/etc/docker/daemon.json,添加"userns-remap": "default"或指定用户如"userns-remap": "tenant-a",然后重启docker服务 - 对于LXD:默认启用user namespace,可通过
lxc config show <container></container>查看security.idmap是否已自动应用对应subuid范围 - 验证方法:进入容器执行
cat /proc/self/uid_map,应看到类似0 100000 65536的三列映射——表示容器内UID 0 映射到宿主机UID 100000
配合ACL与目录权限强化租户边界
user namespace解决的是进程身份隔离,但文件系统访问仍需额外约束,防止租户通过挂载或路径穿越越界:
- 为每个租户创建独立根目录,如
/srv/tenant-a/rootfs,并设置严格基础权限:chmod 700 /srv/tenant-a/rootfs - 使用ACL屏蔽反向访问:
setfacl -m u:tenant-b:--- /srv/tenant-a/rootfs,确保即使容器逃逸也无法读写其他租户数据目录 - 在容器启动时,通过
--rootfs(LXC)或--volume+:ro(Docker)显式挂载,禁用默认继承宿主机敏感路径(如/etc/passwd)
注意事项与常见陷阱
子UID配置看似简单,但几个关键点极易出错:
- 宿主机用户本身不能是UID 0(root),否则无法被remap;必须用普通系统用户(如
adduser tenant-a --shell /bin/false --disabled-password)作为映射主体 - 容器内若需访问宿主机设备节点(如
/dev/sda),必须在映射范围内显式创建对应设备文件,并赋予容器内UID可访问权限,否则会因设备UID不匹配报错 - 启用userns后,部分需要CAP_SYS_ADMIN的能力(如mount)会被限制,应改用更安全的替代方案(如tmpfs挂载、bind mount with proper uid/gid)


















