AWSでDockerコンテナからメタデータサービスへのアクセスをブロックする

概要

環境

  • Ubuntu 18.04.1 LTS (ami-0eeb679d57500a06c)
  • Docker 18.09.7

Docker セットアップ

[host] # apt-get update
[host] # apt-get install docker.io
[host] # systemctl start docker
[host] # systemctl enable docker
[host] # gpasswd -a ubuntu docker  # デフォルトの ubuntu ユーザーで docker コマンドを実行できるように; 設定後再ログイン

確認

  • 何も制限しない状態で Docker コンテナからメタデータサービスへのアクセスを確認してみる
[host] $ docker run -it --rm ubuntu:18.04
[container] # apt-get update
[container] # apt-get install netcat
[container] # nc -vz 169.254.169.254 80
instance-data.ap-northeast-1.compute.internal [169.254.169.254] 80 (?) open    # 接続できた

ファイアウォールを設定する

  • docker のネットワーク設定確認
[host] $ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
6471516562dc        bridge              bridge              local
305df41ba1c0        host                host                local
5ec5bac00e37        none                null                local
  • Docker コンテナ用に 172.17.0.0/16 がブリッジネットワークとして設定されている
$ docker network inspect bridge | jq '.[].IPAM'
{
  "Driver": "default",
  "Options": null,
  "Config": [
    {
      "Subnet": "172.17.0.0/16"
    }
  ]
}
  • iptables のルールを確認
    • Ubuntu では ufw 等のファイアウォール設定ツールも用意されているが、ここでは iptables を利用する (単純に慣れてるので)
    • filter テーブルの FORWARD チェーンで、DOCKER-USER -> DOCKER-ISOLATION-STAGE-1 -> DOCKER-ISOLATION-STAGE-2 -> DOCKER の順に参照される
[host] # iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-USER  all  --  0.0.0.0/0            0.0.0.0/0
DOCKER-ISOLATION-STAGE-1  all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (1 references)
target     prot opt source               destination

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination
DOCKER-ISOLATION-STAGE-2  all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0

Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target     prot opt source               destination
DROP       all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0

Chain DOCKER-USER (1 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
  • iptables の設定を永続化するため、iptables-persistent をインストール
    • 途中で聞かれる選択肢で Yes を選択すると、/etc/iptables/rules.v4, /etc/iptables/rules.v6 に現在の設定が保存される
[host] # apt-get install iptables-persistent
  • DOCKER-USER チェーンの先頭に、docker ブリッジネットワーク (172.17.0.0/16) からリンクローカルアドレス (169.254.0.0/16) へのアクセスを破棄するルールを一時的に追加する
[host] # iptables -I DOCKER-USER 1 -s 172.17.0.0/16 -d 169.254.0.0/16 -j DROP
[host] # iptables -nL DOCKER-USER
Chain DOCKER-USER (1 references)
target     prot opt source               destination
DROP       all  --  172.17.0.0/16        169.254.0.0/16
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
  • Docker コンテナからアクセス確認
    • リンクローカルへのアクセスはブロックされる
    • それ以外のアクセスは通る
[container] # nc -w 1 -vz 169.254.169.254 80
instance-data.ap-northeast-1.compute.internal [169.254.169.254] 80 (?) : Connection timed out
[host] # /etc/init.d/netfilter-persistent save