VPSで複数のDockerコンテナーを実行しています。 nginxプロキシ(Let'sEncryptからの証明書)によるSSL/TLS終了を取得するnextcloudインスタンスがあります。そして、私はopenvpnコンテナを持っています。そのDockerネットワークでは、VPN経由でアクセスできる他のサービス(独自のバインドDNSサーバーとGITサーバー)もホストしています。
次に、VPNを介して次のクラウドインスタンスにもアクセスしたいと思います。もともと私はこれは問題にならないと思っていました。nextcloudインスタンスはインターネット経由でアクセスでき、VPNもインターネットへの接続を提供するためです。しかし、残念ながら到達できません。 VPNを介してサーバー(httpまたはhttps)を丸めると、「ポート80/443:ホストへのルートがありません」というメッセージが表示されます。 VPNに接続しなくても、接続は正しく機能します。
Tracerouteを使用すると、VPSのパブリックIPに正しく到達することがわかります。したがって、ルーティングに問題があると結論付けます。 VPSのパブリックIPのポート80/443をターゲットとするトラフィックは、nginxプロキシコンテナー(上記のポートを公開)に転送/ルーティングされません。
私が理解したように、Dockerはfirewalld/iptablesを使用して、コンテナー間およびコンテナー間のトラフィックをルーティングします。したがって、インターネットからのトラフィック以外のルールがVPNトラフィックに適用されます。 パブリックIPアドレスへのVPNトラフィック(サーバー内部)が対応するコンテナーに正しく転送されるように、どのように構成する必要がありますか? VPNとNoの間の接続を一定/変更せずに維持したい-VPNの状態。これにより、Nextcloudアプリが混乱しないようになっています。
私が試したこと:回避策の可能性を試しました。 VPNのDNSサーバーにネクストクラウドインスタンス用の独自のDNSエントリを追加できます。これは、ネクストクラウドアプリコンテナー(SSL/TLSの終了を失う)またはnginxプロキシのIPをポイントします。最後のケースでは、nginxプロキシは別のホスト名を使用しているため、トラフィックをnextcloudコンテナに転送しません。可能であれば、プロキシ設定を変更しないでください。コンテナの起動時に、またはletsencryptコンパニオンコンテナから自動的に入力されるためです。また、証明書は使用されているFQDNと一致しません。 (外部からと同じFQDNを使用できるように)実際の/パブリックDNS名でマスターゾーンを追加しようとすると、そのTLDからの他のすべてのドメインが転送されなくなります(バインドを構成する可能性はありますか?そのためですか?).
TL; DR: DockerコンテナーからパブリックVPS IPアドレスへのトラフィックは、外部からのトラフィックのように、正しいDockerコンテナーに転送されません。
使用されているコンテナーに関する詳細情報も必要な場合は、リンクとdocker-composeファイルを追加します。
編集:
[root@XXXXXXXX ~]# iptables -S FORWARD
-P FORWARD ACCEPT
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -o br-7e5cecc96f4a -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-7e5cecc96f4a -j DOCKER
-A FORWARD -i br-7e5cecc96f4a ! -o br-7e5cecc96f4a -j ACCEPT
-A FORWARD -i br-7e5cecc96f4a -o br-7e5cecc96f4a -j ACCEPT
-A FORWARD -o br-fd56ce52983e -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-fd56ce52983e -j DOCKER
-A FORWARD -i br-fd56ce52983e ! -o br-fd56ce52983e -j ACCEPT
-A FORWARD -i br-fd56ce52983e -o br-fd56ce52983e -j ACCEPT
-A FORWARD -o br-f1ef60d84b48 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-f1ef60d84b48 -j DOCKER
-A FORWARD -i br-f1ef60d84b48 ! -o br-f1ef60d84b48 -j ACCEPT
-A FORWARD -i br-f1ef60d84b48 -o br-f1ef60d84b48 -j ACCEPT
-A FORWARD -o br-b396aa5a2d35 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-b396aa5a2d35 -j DOCKER
-A FORWARD -i br-b396aa5a2d35 ! -o br-b396aa5a2d35 -j ACCEPT
-A FORWARD -i br-b396aa5a2d35 -o br-b396aa5a2d35 -j ACCEPT
-A FORWARD -o br-83ac9a15401e -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-83ac9a15401e -j DOCKER
-A FORWARD -i br-83ac9a15401e ! -o br-83ac9a15401e -j ACCEPT
-A FORWARD -i br-83ac9a15401e -o br-83ac9a15401e -j ACCEPT
-A FORWARD -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i lo -j ACCEPT
-A FORWARD -j FORWARD_direct
-A FORWARD -j FORWARD_IN_ZONES_SOURCE
-A FORWARD -j FORWARD_IN_ZONES
-A FORWARD -j FORWARD_OUT_ZONES_SOURCE
-A FORWARD -j FORWARD_OUT_ZONES
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -j REJECT --reject-with icmp-Host-prohibited
Dockerはデフォルトで、異なるブリッジに接続されているコンテナの2つの間のトラフィックを許可しません。また、コンテナからdocker自体によって外部にマッピングされているポートへのトラフィックも許可されません。これはすべてiptablesで実装されています。
まず、ポートの外部へのマッピングはiptablesでも行われます。 natテーブルでDNAT
ルールを使用します。これらのルールの場合、Dockerは別のDOCKER
チェーンを作成するため、natのPREROUTING
またはOUTPUT
から同じルールが適用されますテーブル。 DNAT
ルールの前には、Dockerブリッジからのすべてのトラフィックを除外するRETURN
ジャンプがあります。それが最初のハードルです。
次のようになります。
-A DOCKER -i br-one -j RETURN
-A DOCKER -i br-two -j RETURN
-A DOCKER ! -i br-one -p tcp -m tcp --dport EXPOSEDPORT -j DNAT --to-destination 172.17.0.2:INTERNALPORT
そのローカルアドレスのみにポートを公開した場合、DNAT
ルールは-d address
を持つこともできます。その前のDNAT
ルールが原因で、どのDockerブリッジからのトラフィックもRETURN
ルールにヒットできません。また、その上に、DNAT
ルールは、トラフィックが送信されたのと同じブリッジを通過するDNAT
を許可しません。いずれにしても、同じブリッジから[〜#〜] internalport [〜#〜]にすでに到達できるため、これは必要ありません。
異なるブリッジ上のコンテナ間のトラフィックの制限は、iptablesのfilterテーブルに実装されています。 2つのカスタムチェーンがFORWARD
チェーンの先頭にあり、そのチェーンのデフォルトポリシーはDROP
です。 1つはユーザー定義のブリッジを持つコンテナ用で、もう1つはDockerブリッジを持つコンテナ用です:DOCKER-ISOLATION-STAGE-1
。そのチェーンは再びDOCKER-ISOLATION-STAGE-2
を使用します。両方の組み合わせは基本的に、トラフィックがDockerブリッジを去る場合、別のDockerブリッジに入るとすると、DROP
it(ICMPシグナリングがないため、接続がハングするだけです...)
次のようになります。
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-ISOLATION-STAGE-1 -i br-one ! -o br-one -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-two ! -o br-two -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-2 -o br-one -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-two -j DROP
したがって、ブリッジoneからのトラフィックが必要な場合は、ブリッジ上のコンテナによって外部に公開されているポートのDNAT
をヒットしますtwoそして、トラフィックを完全な接続に戻すには、いくつかのことを行う必要があります。
natテーブルのRETURN
チェーンのDNAT
からのトラフィックを停止するDOCKER
ルールを削除します。ソースブリッジのRETURN
を削除する必要があります。そのブリッジのコンテナがRETURN
公開ポートにアクセスすることを許可しない場合は、宛先ブリッジにDNAT
を残すことができます。
iptables -t nat -D DOCKER -i br-one -j RETURN
iptables -t nat -D DOCKER -i br-two -j RETURN
#br-oneの場合はオプション-> br-twofilterテーブルのDOCKER-ISOLATION-STAGE-2
チェーンから両方のブリッジのDROP
ルールを削除します。
iptables -t filter -D DOCKER-ISOLATION-STAGE-2 -o br-one -j DROP
iptables -t filter -D DOCKER-ISOLATION-STAGE-2 -o br-two -j DROP
これで行が開いています。
Dockerはそのルールを頻繁に更新しません(少なくとも、テストした19.03バージョンではそうではありません)。コンテナーを停止または開始または作成したときではなく、Dockerデーモンが再起動したときにのみルールセットが再構築されるようです。サービスの再起動に加えられた変更に対処して、永続的なものに保つことができます。