Docker
ドッカー付きのiptables
サーチ…
前書き
このトピックは、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ルール
作業中です