私の目標は、DockerコンテナーへのアクセスをいくつかのパブリックIPアドレスに制限することです。私の目標を達成するためのシンプルで繰り返し可能なプロセスはありますか? Dockerのデフォルトオプションを使用しているときにiptablesの基本のみを理解していると、非常に難しいことに気づきました。
コンテナーを実行し、パブリックインターネットから見えるようにしたいのですが、選択したホストからの接続のみを許可します。デフォルトのINPUTポリシーをREJECTに設定して、ホストからの接続のみを許可することを期待しています。しかし、DockerのNATルールとチェーンが邪魔になり、入力ルールが無視されます。
誰かが次の仮定の下で私の目標を達成する方法の例を提供できますか?
docker run -d -p 3306:3306 mysql
コンテナーをローカルIPアドレスのみにバインドしても問題ありませんが、Dockerプロセスとホストが再起動しても生き残るiptables転送ルールを適切に設定する方法の説明が必要になります。
ありがとう!
Dockerのファイアウォールルールを使用する場合は、次の2つの点に注意してください。
DOCKER-USER
_チェーンを使用しますPREROUTING
テーブルのnat
チェーンでポートマッピングを行います。これはfilter
ルールの前に発生するため、_--dest
_および_--dport
_はコンテナーの内部IPおよびポートを参照します。元の宛先にアクセスするには、_-m conntrack --ctorigdstport
_を使用できます。例えば:
_iptables -A DOCKER-USER -i eth0 -s 8.8.8.8 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPT
iptables -A DOCKER-USER -i eth0 -s 4.4.4.4 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPT
iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j DROP
_
注:_--ctdir ORIGINAL
_がない場合、これは、コンテナから他のサーバーのポート3306への接続で返される応答パケットにも一致します。私のように最初のルールが_-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
_の場合、これは厳密には必要ありません。すべての応答パケットを処理するためですが、それでも_--ctdir ORIGINAL
_を使用する方が安全です。
Docker v.17.06には、DOCKER-USERと呼ばれる新しいiptablesチェーンがあります。これはカスタムルール用です: https://docs.docker.com/network/iptables/
チェーンDOCKERとは異なり、コンテナーの構築/開始時にリセットされません。したがって、Dockerをインストールしてコンテナを起動する前でも、サーバーをプロビジョニングするためにこれらの行をiptables構成/スクリプトに追加できます。
-N DOCKER
-N DOCKER-ISOLATION
-N DOCKER-USER
-A DOCKER-ISOLATION -j RETURN
-A DOCKER-USER -i eth0 -p tcp -m tcp --dport 3306 -j DROP
-A DOCKER-USER -j RETURN
これで、Dockerが世界のポートを開いたとしても、MySQLのポートは外部アクセス(eth0)からブロックされます。 (これらのルールは、外部インターフェースがeth0であることを前提としています。)
最終的には、iptablesをクリーンアップして、最初にdockerサービスを再起動する必要があります。
UPDATE:この回答はまだ有効ですが、DOCKER-USER
を--ctorigdstport
と組み合わせて使用する@SystemParadoxによる回答の方が優れています。
これは、再起動の間も持続し、internalポートではなくexposedポートに影響を与えることができるソリューションです。
iptables -t mangle -N DOCKER-mysql
iptables -t mangle -A DOCKER-mysql -s 22.33.44.144/32 -j RETURN
iptables -t mangle -A DOCKER-mysql -s 22.33.44.233/32 -j RETURN
iptables -t mangle -A DOCKER-mysql -j DROP
iptables -t mangle -A PREROUTING -i eth0 -p tcp -m tcp --dport 3306 -j DOCKER-mysql
このメソッドを使用して、環境変数を使用するか、etcdで動的に(またはその両方を使用して)、iptablesを自動的に管理するDockerイメージを作成しました。
[〜#〜] update [〜#〜]:2015年には有効でしたが、このソリューションはもはや正しい方法ではありません。
答えは、Dockerのドキュメント https://docs.docker.com/articles/networking/#the-world にあるようです
Dockerの転送ルールでは、デフォルトですべての外部ソースIPが許可されます。特定のIPまたはネットワークのみがコンテナーにアクセスできるようにするには、DOCKERフィルターチェーンの先頭に否定ルールを挿入します。たとえば、ソースIP 8.8.8.8のみがコンテナーにアクセスできるように外部アクセスを制限するには、次のルールを追加できます:
iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP
私がやったことは:
iptables -I DOCKER -i eth0 -s 8.8.8.8 -p tcp --dport 3306 -j ACCEPT
iptables -I DOCKER -i eth0 -s 4.4.4.4 -p tcp --dport 3306 -j ACCEPT
iptables -I DOCKER 3 -i eth0 -p tcp --dport 3306 -j DROP
--iptables
または--icc
オプションには触れませんでした。