DoctableコンテナーがホストIP上のサービスにアクセスできるようにするためのiptablesルールセット


18

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

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

また、特定のコンテナを--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コンテナを実行します:

$ 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

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

それをさらに説明するために(私のアスキーアートデザインのスキルは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

の出力を投稿できますiptables -t nat -nLか?ソースコンテナからpingを実行し、tcpdumpを使用してホスト上のパケットをキャプチャするなど、パケット分析を行いましたか。
ダニエルt。

確かに、これまでの支援に感謝します:pastebin.com/TAaT73nk(コメントに適合しませんでした。)- 編集 ->有効期限のないペーストビンへのリンクを更新しました。
ダイノム

私はあなたの問題を正しく理解していなかったのかもしれませんが、ホストでDNSクエリを許可するルールがありません。また、ip_forwardは有効になっていますか?
Laurentiu Roescu

こんにちは@LaurentiuRoescu。プライベートインターフェイス上のすべての接続$ cat /proc/sys/net/ipv4/ip_forward -> 1-A INPUT -i eth1 -j ACCEPT受け入れます。どんなルールが欠けていますか?
ダイノム

2
コンテナからのパケットは、eth1ではなくdocker0インターフェースから来ると思います。試してください-A INPUT -i docker0 -j ACCEPT
Laurentiu Roescu

回答:


14

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

-A INPUT -i docker0 -j ACCEPT

2
ダイノム、あなたがこれから取り去りたいかもしれない教訓は、あなたのすべての拒否を記録することは、例えば、であるということiptables -A INPUT -j LOGです。スタンプIN=docker0は、ルールの微調整が必​​要かどうかを判断するのに非常に役立ちます。Laurentiuの仕事を奪ってはいけません。それは素晴らしいものでした-私からの+1です!
MadHatterはモニカをサポートしています

5
UFWを使用する人々のために、ここで私がホストにドッカーコンテナからすべての通信を許可するようにやったことです:UFWはdocker0上で許可する
アリ[OK]を

0

私は非常に似た状況に遭遇しましたが、追加-A INPUT -i docker0 -j ACCEPTすると、Dockerホストのeth0インターフェイスを介したコンテナへのすべてのアクセスが開かれますが、これは絶対に意図したものではありません。

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


-i docker0これがdocker0ネットワーク経由で到着しないトラフィックに影響を与えないようにする必要があります。ただし、文法は明確ではありません。おそらく、eth0を介したdockerホストからの発信アクセスが有効になっていると言っていたかもしれません。よりターゲットを絞ったルールは、必要なだけ開くことができることに同意します。
mc0e
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.