同じホストのLXC、Docker、iptables、コンテナからコンテナへのポート転送のタイムアウト

同じホストのLXC、Docker、iptables、コンテナからコンテナへのポート転送のタイムアウト

読んでくれてありがとう!ホストとして使用するパブリックサーバー(debian 10)がありLXC(LXDではなく)、Dockerこれら2つのコンテナサービスはほとんど元の構成で実行されます(LXCはlxc-netとそのlxcbr0ブリッジを使用し、Dockerはそのdocker0ブリッジを使用します)。コンテナはNATを通過します。

ほとんどすべてが正常です(コンテナ内のインターネットアクセス、ポート転送など)。を除いてホストパブリックIP(したがってポート転送)を使用して内部から直接コンテナにアクセスすることはできません。ドッカーが始まるとき(そしてiptables: true)。

LXC container web例:IPが物理ホストを指すでホストされているWebサイトにアクセスしたいと思います。
外部から(例:マイコンピュータ):効果がある
ホスト自体から:効果がある
他のLXCコンテナから:効果がある
Dockerコンテナから:効果がある
からweb container itself停止する

LXCコンテナは、ネットワーキング用にシンプルな自家製の.NETを使用しますiptables rules

iptables -t nat -A PREROUTING -d ${MY_PUBLIC_IP}/32 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.0.0.10:443
iptables -t nat -A OUTPUT -o lo -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.0.0.10:443
iptables -t nat -A POSTROUTING -s 10.0.0.0/8 ! -d 10.0.0.0/8 -j MASQUERADE # added by LXC

数週間、私はこの問題を解決しようと必死に努めましたが、成功しませんでした。ルールを修正し、変装ルールを追加し、ルールを文書化してみましたが、自分が見えない誤解があるかもしれません。
dockerを使用してdockerを実行または停止すると、iptables: falseこの問題を解決できます。
回避策の1つは、コンテナのループバックインターフェイスを使用するように/ etc / hostsを調整することですが、ドメインが多すぎるため、これを避けることをお勧めします。

私の考えでは、DOCKER-USERルールが私の要求をブロックしているようですが、回避策が見つかりません。

私よりも経験豊富な人が私が間違っていることを教えてもらえますか?

答え1

あなたは一つ持っている必要がありますヘッドピン正しく動作するように設定します。

また、以下に説明するのは、同じLAN上の他のLXCコンテナで動作する奇妙な世界であり、おそらく動作しないはずですブリッジネットワークフィルタ


2つの異なる効果を得ることができます。 1つは非常に微妙で、すべてを理解する方法を変更します。

  • Dockerはカーネルモジュールをbr_netfilterロードします。私の答えで説明したようにiptableはLinuxブリッジとどのように機能しますか?、これiptablesルールの影響ブリッジ額縁。

    このルールは通常、ルーティングパスで呼び出す必要があります。

    iptables -t nat -A PREROUTING -d ${MY_PUBLIC_IP}/32 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.0.0.10:443
    

    ターゲットを10.0.0.10に変更します。これは次のことも意味します。

    iptables -t nat -A POSTROUTING -s 10.0.0.0/8 ! -d 10.0.0.0/8 -j MASQUERADE # added by LXC
    

    今は発動しません。

    したがって、クライアントコンテナが10.0.0.11の場合、結果は次のようになります。ネットワークコンテナ応答まっすぐブリッジパスを介して10.0.0.11に到達します。 10.0.0.11は未知のIPアドレス10.0.0.10(MY_PUBLIC_IPではない)から接続を受信するため、TCP RSTが再送信されます。これは、Dockerが実行されていない場合(接続がまったく関連していない場合でも)、LXC - > LXCケースが機能しないことを意味します。

    そしてbr_netfilterロードされたブリッジフレームは返品〜によってつながるとネットワークアドレス変換。したがって、10.0.0.11に応答すると、10.0.0.10はブリッジパスから傍受され、ソースMY_PUBLIC_IPに再デDNAされます。 10.0.0.11 MY_PUBLIC_IPでまだ応答を見ました:透明なヘアピンが発生しました。

    それでも大丈夫ですが、奇妙な行動それを念頭に置かなければならず、当然のことではありません。一般的な動作は、ブリッジパケットを変更しないことです。繰り返しますが、通常の行動はiptablesFORWARDチェーンはブリッジコンテナをフィルタリングしませんが、現在フィルタリングされます。

    これについて詳しくはこちらをご覧ください。模式図。下部の青色(ブリッジレベル)背景の緑色(ネットワークレベル)ボックスはで有効になりますbr_netfilter。図3cを確認することもできます。Linuxベースのブリッジのebtables/iptables相互作用

  • 接続の場合ネットワークbr_netfilter場合によっては(モジュールをロードしなくても)10.0.0.10から10.0.0.10まで、有線を介してコンテナとそれ自体の間に接続があるかもしれませんが、動作しません。デフォルトでは、ネットワークスタックは独自のソースアドレスBagで受信したリモートデータを削除します。しかし、バグのように見える別の問題があります。下記をご覧ください。


したがって、現在の設定にバンドル倉庫を適用するには、送信元IPアドレスをルーティングされたIPアドレスに変更する必要があります。 8.8.8.8などは何でも構いませんが、直接制御する方が良いです。 MY_PUBLIC_IP、または実用的でない場合は割り当てられたアドレスlxcbr0(10.0.0.1 と仮定します。) これは、Web サービスがログ内の独自の IP アドレスを表示できないことを意味します。これは完全に避けられないことです。

ただし、説明できない理由で試行錯誤(ネットフィルタでパケットを追跡)した後返品無差別モードは、ブリッジ自体のインターフェイスで有効にする必要があります。lxcbr0それ以外の場合は、ip nat / PREROUTINGとブリッジフィルタ/ INPUTの間でパケットが消えます(この順序でもう一度確認してください)。図3c)、したがってip nat / POSTROUTINGに達しません。そうだ第8章で説明されている動作予想通りには起こらなかった。

ip link set lxcbr0 promisc on

次に、次を追加します。

iptables -t nat -A POSTROUTING -s 10.0.0.10 -p tcp --dport 443 -j SNAT --to-source $MY_PUBLIC_IP

または:

iptables -t nat -A POSTROUTING -s 10.0.0.10 -p tcp --dport 443 -j MASQUERADE

または、DNATedストリームと一致させます(SNATターゲットでも機能します)。

iptables -t nat -A POSTROUTING -s 10.0.0.10 -m conntrack --ctstate DNAT -j MASQUERADE

最新のカーネル(5.3以降と考えています)では、ネットワークネームスペースまたはブリッジ(たとえば)ごとにip link set lxcbr0 type bridge nf_call_iptables 1有効を選択的に有効または無効にできますnet.bridge.bridge-nf-call-iptables。しかし、Dockerがこれをどのようにトリガーするのかわかりません(通常は次の理由による)。-m physdev iptables一致しますが、唯一のケースではないかもしれません)Dockerが通常どおりに機能するようにしながら、この機能を無効にする場所を知ることは困難です。

関連情報