限制对特定 Docker 容器的 AWS EC2 元数据的访问

限制对特定 Docker 容器的 AWS EC2 元数据的访问

我在 AWS EC2 实例上运行 docker,我想阻止某些容器访问 EC2 实例元数据(IP 地址为 169.254.169.254)。我认为我可以通过以特定用户(例如 userx)身份运行这些容器来实现这一点,并遵循以下 ip 表规则:

$ iptables -A OUTPUT -m owner --uid-owner userx -d 169.254.169.254 -j DROP

当容器使用主机网络运行时,这将按预期阻止连接:

$ docker run -it --rm --network host -u $(id -u userx):$(id -g userx) appropriate/curl  http://169.254.169.254/latest/meta-data/
...blocks..

但遗憾的是,当容器在其自己的网络中运行时,允许连接

$ docker run -it --rm -u $(id -u userx):$(id -g userx) appropriate/curl  http://169.254.169.254/latest/meta-data/
...show metadata...

我该如何实现这一点?或者,是否有其他技术可以让特定容器获得完全网络访问权限,同时阻止实例元数据?

答案1

您的问题是OUTPUT无法捕获从容器中出来的数据包FORWARD

这是为什么?

每个 Docker 容器都在自己的网络命名空间中运行。每个网络命名空间都有自己的路由表和 iptables 规则,其行为方式与单独的物理机器完全相同。

在 iptables 中:

  • INPUT匹配发往本地进程的数据包
  • FORWARD匹配从一个网络接口进入并从另一个网络接口出去(通过路由)的数据包。
  • OUTPUT匹配来自本地进程的数据包

关键是“本地进程”的意思是“此网络命名空间中的进程”,而不是“此机器中的进程”。

我们来分析一下发生了什么:

  • 数据包由 Docker 容器的网络命名空间中的进程生成。
  • 它们通过OUTPUT容器的网络命名空间 iptables 中的 iptables 链。(它是空的!)
  • 它们被路由出了veth接口。
  • 它们从接口到达主机的网络命名空间veth
  • 主机网络命名空间查阅路由表并决定它们需要离开例如eth0
  • 它们穿过FORWARD主机网络命名空间中的 iptables 链。
  • 他们出去了eth0

因此,解决方案是将规则放入FORWARD链中。

问题是-m owner在 中不起作用FORWARD。根据man iptables-extensions

此匹配仅在 OUTPUT 和 POSTROUTING 链中有效。转发的数据包没有任何与之关联的套接字。

您可以对容器的 IP 地址进行硬编码,或者将要过滤的容器放在特殊网络中,并匹配整个范围。类似这样的操作应该有效:

    # single container
    iptables -A FORWARD -s 172.17.0.4 -d 169.254.169.254 -j DROP

    # or entire network
    iptables -A FORWARD -s 172.17.0.0/16 -d 169.254.169.254 -j DROP

此外,owner无论如何使用可能都不是一个好主意,因为如果图像中有的话,docker 容器内的进程可以通过 setuid 二进制文件(如 sudo)更改其 uid。

相关内容