在 Docker Nginx 容器中,我可以丢弃哪些功能?

11
我正在Docker容器中运行Nginx,并且出于安全原因,我希望尽可能地删除Linux功能。那么我可以删除哪些功能呢?
该镜像类似于标准的Docker Nginx Alpine镜像,链接如下:https://github.com/nginxinc/docker-nginx/blob/0c7611139f2ce7c5a6b1febbfd5b436c8c7d2d53/mainline/alpine/Dockerfile,它以root身份启动Nginx,然后将工作进程作为用户“nginx”运行。
root@instance-1:/opt/ed# docker-compose exec web bash
bash-4.3# # Now we're inside the container.
bash-4.3# ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 /bin/sh -c /etc/nginx/run-envsubst.sh && nginx
   10 root       0:00 nginx: master process nginx
   11 nginx      0:00 nginx: worker process
   12 nginx      0:00 nginx: cache manager process
   14 root       0:00 bash
   18 root       0:00 ps aux

监听80和443端口,并使用Docker-Compose的'volume: ....'指令挂载一些目录。

显然,这些是Docker默认授予容器的功能:

s.Process.Capabilities = []string{
    "CAP_CHOWN",
    "CAP_DAC_OVERRIDE",
    "CAP_FSETID",
    "CAP_FOWNER",
    "CAP_MKNOD",
    "CAP_NET_RAW",
    "CAP_SETGID",
    "CAP_SETUID",
    "CAP_SETFCAP",
    "CAP_SETPCAP",
    "CAP_NET_BIND_SERVICE",
    "CAP_SYS_CHROOT",
    "CAP_KILL",
    "CAP_AUDIT_WRITE",
}

从这里开始:https://github.com/docker/docker/blob/master/oci/defaults_linux.go#L62-L77

我在这里找到了链接:https://docs.docker.com/engine/security/security/#linux-kernel-capabilities,该页面指出:“默认情况下,Docker会放弃除所需之外的所有特权”,这可能意味着不需要放弃任何特权?...

...但是有这篇Red Hat博客文章讲述了放弃很多这些能力的问题-因此似乎(某些)默认的能力实际上并不需要。我不确定该相信什么,我想知道人们知道哪些能力可以(应该)被放弃。

(我可以尝试自己测试,但即使我测试过减少了一个能力,事情在几个小时或几天内似乎运作正常-我可能仍然删除了错误的能力?问题可能会发生,甚至更晚?因此,询问别人和自己测试似乎比仅仅进行测试更安全)

(我很惊讶为什么这个问题在其他地方没有回答?很多人使用在docker中使用Nginx,因此想要放弃特权嘛?)


我觉得你已经回答了自己的问题。你确定了它所需的功能,现在你可以通过仅指定允许的功能来删除其他功能。 - Matt Schuchard
@MattSchuchard 我不明白 - 我不认为我确定了 Nginx 容器需要的功能?上面的列表是 Docker 默认授予任何容器的功能。其中一些是必需的,我想,但可能不是全部。我想知道列表中哪些功能是不必要的,可以被删除。(我更新了问题以澄清列表是 Docker 默认授予任何容器的功能。) - KajMagnus
哦,我把seccomp和capabilities搞混了。好的,你可以运行你的容器并使用pscapfilecap来查看你的容器需要什么capabilities。使用captest来测试它们。然后,使用--cap-drop ALL --cap-add foo除了你需要的capability之外删除所有的capabilities。在这里查看更多信息:https://github.com/docker/labs/tree/master/security/capabilities。让我知道你的进展如何。 - Matt Schuchard
1
@MattSchuchard 谢谢,+有趣的链接。现在时间紧迫,可能需要一周才能有时间测试。那时我会通知你的,好吗? - KajMagnus
1个回答

12

我想知道同样的事情,所以我进行了一些研究。请注意这不是专家答案。

简短回答:如果您以用户身份启动nginx并使用非特权端口(>1024),则可以放弃所有权限。这在Nginx in Docker without Root中有描述,并且一些额外信息可以在Running Nginx as non root user中找到。

特别推荐使用ajhaydock/nginx nginx镜像,并同时添加--cap-drop=ALL(尽管我不建议使用此镜像,因为它目前相当大:700MB)。

更长的答案:所需权限可能会因您的配置和是否要以root身份启动nginx而有所不同。

让我们从官方docker镜像及其默认配置开始。最低限度的权限如下:

docker pull nginx:alpine
docker run -p 8080:80 --cap-drop=all \
    --cap-add=chown --cap-add=dac_override \
    --cap-add=setgid --cap-add=setuid \
    --cap-add=net_bind_service \
    nginx:alpine

您可以使用这些命令检查本地端口8080上的欢迎页面,如果删除任何功能,则进程会在启动时崩溃。(请注意,根据Secure Your Containers with this One Weird Trick,需要dac_override意味着他们可能做错了。)
显然,只有在监听特权端口如80和443时才需要net_bind_service。由于我们可以自由重定向,因此可以通过仅在更高的端口上侦听来放弃它:
docker cp nginx:/etc/nginx/conf.d/default.conf .
sed -i 's/listen\s*80;/listen 8080;/' default.conf
docker rm nginx
docker run -p 8080:8080 --cap-drop=all \
    --cap-add=chown --cap-add=dac_override \
    --cap-add=setgid --cap-add=setuid \
    -v $(pwd)/default.conf:/etc/nginx/conf.d/default.conf \
    nginx:alpine

依然有效。

通过将nginx作为非root用户运行,还可以放弃其他特权。在这种情况下,您不能使用user nginx;指令,而应该在Dockerfile中使用USER nginx。这也防止您使用特权端口。

其他可能对他人有帮助的资源:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接