AWSでDockerコンテナからメタデータサービスへのアクセスをブロックする
概要
- Amazon VPC では、リンクローカルの 169.254.169.254 で EC2 インスタンスの稼働に必要なメタデータサービスが HTTP で提供されている
- セキュリティ上の理由から、Docker コンテナからホストのメタデータサービスへのアクセスをブロックしたいことが多い
- ECS を利用せず、EC2 で素の Docker を利用する際に、Docker コンテナからホストのメタデータサービスへのアクセスをブロックする方法をメモしておく
- AWS VPC が備えるセキュリティグループやネットワーク ACL では、リンクローカルアドレス、または VPC で予約されている IPv4 アドレスに対する通信をブロックすることができない
- AWS ドキュメント » Amazon VPC » ユーザーガイド » セキュリティ より
Amazon セキュリティグループとネットワーク ACL は、リンクローカルアドレス (169.254.0.0/16) または AWS 予約済み IPv4 アドレスとやり取りされるトラフィックをフィルタリングしません。 予約済みアドレスは、サブネットの最初の 4 個の IPv4 アドレス (VPC の Amazon DNS サーバーアドレスを含む) です。 同様に、フローログは、これらのアドレスを出入りする IP トラフィックをキャプチャしません。 これらのアドレスでは、ドメインネームサービス (DNS)、動的ホスト構成プロトコル (DHCP)、Amazon EC2 インスタンスメタデータ、Key Management Server (KMS - Windows インスタンスのライセンス管理)、およびサブネットでのルーティングといったサービスをサポートしています。 追加のファイアウォールソリューションをインスタンスで実装すれば、リンクローカルアドレスとのネットワーク通信をブロックできます。
- AWS ドキュメント » Amazon VPC » ユーザーガイド » セキュリティ より
- ホスト OS のファイアウォール機能を利用し、Docker で設定されるゲスト用の bridge ネットワークから、ホストのメタデータサービスへのアクセスをブロックするルールを追加する
- AWS VPC が備えるセキュリティグループやネットワーク ACL では、リンクローカルアドレス、または VPC で予約されている IPv4 アドレスに対する通信をブロックすることができない
環境
- 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 のルールを確認
[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
- iptables の設定を永続化する
[host] # /etc/init.d/netfilter-persistent save