Amazon-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...
我怎樣才能使這項工作?或者,是否有其他技術可以在阻止實例元數據的同時為特定容器提供完整的網路訪問權限?
您的問題是
OUTPUT
沒有擷取從容器中出來的數據包。FORWARD
做。這是為什麼?
每個 Docker 容器都在自己的網路命名空間中執行。每個網路命名空間都有自己的路由表和 iptables 規則,其行為就像是一台單獨的物理機器一樣。
在 iptables 中:
INPUT
匹配到本地程序的數據包FORWARD
匹配從一個網路介面傳入並從另一個網路介面傳出(被路由通過)的數據包。OUTPUT
匹配來自本地程序的數據包關鍵是“本地程序”是指“這個網路命名空間中的一個程序”,而不是“這個機器中的一個程序”。
我們來分析一下是怎麼回事:
- 數據包由 Docker 容器的網路命名空間中的程序生成。
- 它們通過
OUTPUT
容器的網路命名空間 iptables 中的 iptables 鏈。(這是空的!)- 他們被路由出
veth
介面。veth
它們從介面到達主機的網路命名空間。- 主機網路命名空間查閱路由表並決定他們需要離開例如
eth0
.- 它們通過主機網路命名空間中的 iptables
FORWARD
鏈。- 他們出去
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,如果映像中有的話。