web-dev-qa-db-ja.com

Iptablesルールセットにより、DockerコンテナーはホストIP上のサービスにアクセスできます

Dockerコンテナーからホストのプライベートインターフェイス(ip)にアクセスできません。私のIptablesルール(またはおそらくルーティング)に関連していることはかなり確実です。 --net=Hostフラグをdocker runに追加すると、すべてが期待どおりに機能します。同様に、INPUTポリシーがリベラル-P INPUT ACCEPTに従っていることを指定すると、期待どおりに機能します。しかし、これらは私が避けたい、望ましくない、安全でないオプションです。

これは私のサービス(DNS)に固有のものではないため、それをdockerと組み合わせて検索すると別の(人気のある)問題領域で発生し、検索結果にノイズが加わるため、問題から除外しました。

また、特定のコンテナーは--net = Hostオプションを指定して実行する必要があるため、Dockerコンテナーのリンクは実行可能なオプションではありません。リンクを防止し、可能な場合は一貫した状況を作成したいと考えています。

以下のIptablesルールがあります。 CoreOS、Digital Ocean、Dockerの組み合わせだと思います。

-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth1 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT

私の(関連する)ホストインターフェイス:

3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.129.112.210/16 brd 10.129.255.255 scope global eth1
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever

そして、私はドッカーコンテナを実行します:

$ docker run --rm -it --dns=10.129.112.210 debian:jessie # Specifying the DNS is so that the public DNS servers aren't used.

この時点で、10.129.112.210:53にバインドされたローカルサービスを使用できるようにしたいと考えています。したがって、次のように応答する必要があります。

$ ping google.com
^C
$ ping user.skydns.local
^C

ホストから同じコマンドを実行すると:

$ ping photo.skydns.localPING photo.skydns.local (10.129.112.206) 56(84) bytes of data.
64 bytes from 10.129.112.206: icmp_seq=1 ttl=64 time=0.790 ms
^C

私のresolv.conf

$ cat /etc/resolv.conf
nameserver 10.129.112.210
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4

ここでのポイントは、パブリックホストにアクセスすることではなく、ホストで利用可能なローカルDNSサービスを使用して(別のdockerインスタンスを介して)内部のホストにアクセスすることです。

さらに説明すると(私のアスキーアートデザインスキルは私のiptables fuを上回っているので、この時点で十分です)。

 ______________________________________________
|  __________________________           Host   |
| |   Docker DNS container   |                 |
|  ``````````````````````|```                  |
|                        |                     |
|     ,----------,---( private n. interface )  |
|     |          |                             |
|     |          |   ( public  n. interface )---
|     |          |                             |
|     |          |   ( loopbck n. interface )  |
|     |          |                             |
|     |          |                             |
|     |        __|_______________________      |
|     |       | Docker service container |     |
|     |        ``````````````````````````      |
|     |                                        |
|     |                                        |
| [ Local Host service using DNS. ]            |
|                                              |
|______________________________________________|

  private (Host) network interface: eth1 (10.129.0.0/16)
  Docker network interface: docker0 (172.17.0.0/16)

私はさまざまな例のIptables構成を検索、読み取り、および適用しましたが、何が起こっているのかを理解し、それにより望ましい結果を得るための、より「高度な」Iptablesルールをほとんど知りません。

iptables -t nat -nLの出力:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0

Chain DOCKER (2 references)
target     prot opt source               destination

cat /proc/sys/net/ipv4/ip_forwardの出力:

1
18
Dynom

コンテナはdocker0インターフェースを使用してホストと通信します。コンテナーからのトラフィックを許可するには、以下を追加します。

-A INPUT -i docker0 -j ACCEPT
15

私は非常に似た状況に遭遇しましたが、-A INPUT -i docker0 -j ACCEPTは、Docker Hostのeth0インターフェイスを介して、コンテナへのすべてのアクセスを開きますが、これは私が意図したものとはまったく異なります。

そして、私は自分のコンテナーがホストネットワークから完全にシャットダウンするのではなく、ホストインターフェイスへのアクセスが制限されている(ポート22のみ)ことに気付いたので、iptablesルールを確認し、これを担当するはずのチェーンIN_public_allowにルールを見つけました。ルールは-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT。そこで、コンテナーが他の必要なホストポートにアクセスできるように、同様のルールを追加しました。これは、コンテナーへのホストネットワークアクセスを開くためのもう少し正確な方法になると思います。

0
L3w1s