サーチ…


前書き

このトピックは、iptablesを使用して外部からのドッカーコンテナーへのアクセスを制限する方法についてです。

不本意な人のために、例を確認することができます。他の人にとっては、新しいルールを構築する方法を理解するために、コメントセクションを読んでください。

構文

  • iptables -I DOCKER [RULE ...] [ACCEPT | DROP] //ルールを追加するにはDOCKERテーブルの先頭
  • iptables -D DOCKER [RULE ...] [ACCEPT | DROP] // DOCKERテーブルからルールを削除するには
  • ipset restore </etc/ipfriends.conf // ipset ipfriendsを再設定するには

パラメーター

パラメーター詳細
ext_if Dockerホスト上の外部インターフェイス。
XXX.XXX.XXX.XXX Dockerコンテナがアクセスする特定のIPを指定する必要があります。
YYY.YYY.YYY.YYY Dockerコンテナがアクセスする別のIPを与える必要があります。
ipfriends DockerコンテナにアクセスできるIPを定義するipset名。

備考

問題

Dockerコンテナのiptablesルールを設定するのはちょっと難しいです。最初は、 "古典的な"ファイアウォールルールがこのトリックを行うべきだと思うでしょう。

たとえば、nginx-proxyコンテナ+いくつかのサービスコンテナを設定して、HTTPSを介していくつかのパーソナルWebサービスを公開しているとします。このようなルールでは、IP XXX.XXX.XXX.XXXのWebサービスにのみアクセスする必要があります。

$ iptables -A INPUT -i eth0 -p tcp -s XXX.XXX.XXX.XXX -j ACCEPT
$ iptables -P INPUT DROP

それは動作しません、あなたのコンテナは誰にとってもアクセス可能です。

実際、Dockerコンテナはホストサービスではありません。ホストの仮想ネットワークに依存し、ホストはこのネットワークのゲートウェイとして機能します。また、ゲートウェイに関しては、ルーティングされたトラフィックはINPUTテーブルで処理されず、FORWARDテーブルによって処理されます。

しかし、それはすべてではありません。実際、Dockerデーモンは、コンテナのネットワーク接続に関して魔法を発揮し始めると、多くのiptablesルールを作成します。特に、FORWARDテーブルからこの新しいテーブルにトラフィックを転送することによって、コンテナに関するルールを処理するDOCKERテーブルが作成されます。

$ iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-ISOLATION  all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (2 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:https
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:http

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

ソリューション

公式の文書( https://docs.docker.com/v1.5/articles/networking/)をチェックすると、Dockerコンテナのアクセスを1つの特定のIPに制限するための最初の解決策が与えられます。

$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP

実際、DOCKERテーブルの一番上にルールを追加することは良い考えです。 Dockerによって自動的に設定されるルールに干渉することはなく、簡単です。しかし、2つの主要な欠点:

  • まず、2つのIPからアクセスする必要がある場合はどうすればよいでしょうか?ここでは1つのsrc IPだけを受け入れることができますが、他のものはそれを防ぐ手段を持たずに削除されます。
  • 第二に、ドッカーがインターネットにアクセスする必要がある場合はどうすればよいですか?サーバー8.8.8.8だけが応答することができるので、リクエストは正常に処理されません。
  • 最後に、他のロジックを追加したい場合はどうしますか?たとえば、HTTPプロトコルを使用しているWebサーバーにアクセスするすべてのユーザーにアクセスできますが、その他すべてのアクセスを特定のIPに制限します。

最初の観測では、 ipsetを使うことができます。上記のルールで1つのIPを許可する代わりに、事前定義済みのIPセットからすべてのIPを許可します。ボーナスとして、ipsetはiptableルールを再定義する必要なしに更新することができます。

$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP

第2の観察では、これはファイアウォールの標準的な問題です。ファイアウォールを介してサーバーに接続することが許可されている場合、ファイアウォールはサーバーがユーザーの要求に応答するように許可する必要があります。これは、確立された接続に関連するパケットを認可することによって行うことができる。ドッカーロジックの場合、次のようになります。

$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

最後の観察は1つのポイントに焦点を当てます:iptablesのルールは不可欠です。実際に、いくつかの接続(ESTABLISHED接続に関するものを含む)を受け入れるための追加ロジックは、DROPルールの前にDOCKERテーブルの最上位に置かなければなりません。

テーブルの先頭にルールを挿入するiptableの-Iオプションを使用するので、以前のiptablesルールは逆の順序で挿入する必要があります。

// Drop rule for non matching IPs
$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP
// Then Accept rules for established connections
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT 
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 3rd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 2nd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 1st custom accept rule

これを念頭に置いて、この設定を示す例を確認することができます。

DockerコンテナへのアクセスをIPセットに限定する

まず、必要に応じてipsetをインストールします。それを行う方法を知るには配布物を参照してください。一例として、Debianのようなディストリビューションのコマンドがあります。

$ apt-get update
$ apt-get install ipset

次に、設定ファイルを作成して、Dockerコンテナへのアクセスを開くIPを含むIPセットを定義します。

$ vi /etc/ipfriends.conf
# Recreate the ipset if needed, and flush all entries
create -exist ipfriends hash:ip family inet hashsize 1024 maxelem 65536
flush
# Give access to specific ips
add ipfriends XXX.XXX.XXX.XXX
add ipfriends YYY.YYY.YYY.YYY

このipsetをロードしてください。

$ ipset restore < /etc/ipfriends.conf

Dockerデーモンが実行されていることを確認してください。次のコマンドを入力した後でもエラーは表示されません。

$ docker ps

iptablesのルールを挿入する準備が整いました。あなたは注文を尊重しなければなりません

// All requests of src ips not matching the ones from ipset ipfriends will be dropped.
$ iptables -I DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
// Except for requests coming from a connection already established.
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

新しいルールを作成する場合は、追加したすべてのカスタムルールを削除してから新しいルールを挿入する必要があります。

$ iptables -D DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
$ iptables -D DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Dockerデーモン起動時の制限アクセスを設定する

作業中です

一部のカスタムiptablesルール

作業中です



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow