tim*_*bod 0 iptables amazon-ec2 docker
我在 AWS EC2 实例上运行 docker,并且希望阻止某些容器访问 EC2 实例元数据(IP 地址为 169.254.169.254)。我认为我可以通过在存在以下 ip 表规则的情况下以特定用户(例如 userx)运行这些容器来实现此目的:
$ iptables -A OUTPUT -m owner --uid-owner userx -d 169.254.169.254 -j DROP
Run Code Online (Sandbox Code Playgroud)
当容器通过主机网络运行时,这会按预期阻止连接:
$ docker run -it --rm --network host -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...blocks..
Run Code Online (Sandbox Code Playgroud)
但遗憾的是,当容器在自己的网络中运行时允许连接
$ docker run -it --rm -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...show metadata...
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?或者,是否有其他一些技术可以为特定容器提供完整的网络访问权限,同时阻止实例元数据?
您的问题是OUTPUT无法捕获来自容器的数据包。FORWARD做。
这是为什么?
每个 Docker 容器都在自己的网络命名空间中运行。每个网络命名空间都有自己的路由表和 iptables 规则,并且其行为就像一台单独的物理机一样。
在 iptables 中:
INPUT匹配发往本地进程的数据包FORWARD匹配传入一个网络接口并传出另一个网络接口(通过路由)的数据包。OUTPUT匹配来自本地进程的数据包关键是“本地进程”是指“这个网络命名空间中的进程”,而不是“本机中的进程”。
我们来分析一下这是怎么回事:
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
Run Code Online (Sandbox Code Playgroud)
另外,owner无论哪种方式使用可能都不是一个好主意,因为 docker 容器内的进程可以通过例如 setuid 二进制文件(如 sudo)更改其 uid(如果镜像中有的话)。
| 归档时间: |
|
| 查看次数: |
1772 次 |
| 最近记录: |