当尝试在以以下方式启动的 systemd 容器内运行 Apache 时systemd-nspawn --private-users=pick ...
(--private-users=false
与这解决方案)我遇到了这个错误:
Permission denied: AH00072: make_sock: could not bind to address ...:999
令我困惑的是,容器已被授予功能CAP_NET_BIND_SERVICE
(getpcaps 1
容器内部也证实了这一点),--capability=help
表明该功能受支持,并且netcat -l 999 -s ...
(也在容器内部)显然可以很好地监听同一端口。
我错过了什么?该功能是否应该允许容器内的进程打开主机上的知名端口,无论它们的 PID 是什么?
更新我在调用 时犯了一个错误netcat
。正确的命令行是netcat -vl -p 999 -s ...
,现在它会产生“无法使用 bind 抓取 ...:999:权限被拒绝”。因此,实际上此时 Apache 和 netcat 都无法绑定,而且这不是 Apache 特有的。关于配置的另外两个事实:容器以root
(映射到主机上的非 root pid) 身份运行,iptables
在主机上为空。
更新因此也许能力CAP_NET_BIND_SERVICE
只是无法超越用户命名空间。
答案1
我得出的结论是,CAP_NET_BIND_SERVICE
具体的能力和一般的能力都不能超越用户命名空间。来自user_namespaces(7)
:
用户命名空间隔离与安全相关的标识符和属性,特别是用户 ID 和组 ID(参见 credentials(7))、根目录、密钥(参见 keyrings(7))和功能(参见 capabilities(7))。
...
使用 CLONE_NEWUSER 标志通过 clone(2) 创建的子进程一开始就拥有新用户命名空间中的一整套功能。同样,使用 unshare(2) 创建新用户命名空间或使用 setns(2) 加入现有用户命名空间的进程也会获得该命名空间中的一整套功能。另一方面,该进程在父级(在 clone(2) 的情况下)或先前(在 unshare(2) 和 setns(2) 的情况下)用户命名空间中没有任何功能,即使新命名空间是由 root 用户(即 root 命名空间中用户 ID 为 0 的进程)创建或加入的。
...
在用户命名空间内拥有能力,则允许进程仅对该命名空间所管辖的资源执行操作(需要特权)。换句话说,在用户命名空间内拥有能力,则允许进程对该用户命名空间所关联的(非用户)命名空间所管辖的资源执行特权操作(请参阅下一小节)。
从network_namespaces(7)
:
一个物理网络设备只能存在于一个网络命名空间中。
由于我的情况涉及与主机主 IP 地址的绑定,因此相关物理网络设备可能必须由内核的根网络命名空间管理。CAP_NET_BIND_SERVICE
我的容器的用户命名空间中的功能可能与此无关,因为根网络命名空间与该用户命名空间无关,而是与内核的根用户命名空间有关。所以我(大概)在这里运气不佳。