解決が必要な問題

解決が必要な問題

私のコンピュータは、非常に厳格なnftables設定を有効にした2つのDockerコンテナを実行しています。この方法を維持したいのですが、Dockerコンテナへの外部アクセスをホワイトリストに追加します。

コンテナはポート80と6200を開きます。 dockerサービスはiptablesが無効になっている状態で開始されます。

これは私の試みを含む現在のファイアウォール構成です。icmpsshおよびはhttpすでにhttps開いています。 Dockerの場合は、httpポート80とアプリケーション固有のポート6200のみが必要です。私は192.168.0.0/16できるだけ制限的にDockerへのアクセスのみを許可しようとします。

 table inet filter {
    chain input {
            type filter hook input priority 0; policy drop;
            iif lo accept
            iif eno2 icmp type echo-request accept
            iif eno2 ip 192.168.0.0/16 tcp dport 22 accept
            iif eno2 ip 192.168.0.0/16 tcp dport { http, https, 6200 } accept
    }

    chain forward {
            type filter hook forward priority 0; policy drop;
    }

    chain output {
            type filter hook output priority 0; policy drop;
    }
}

docker0インターフェイスに追加のルールを追加しようとしましたが、成功しませんでした。修正する必要があると思いますかchain forward

答え1

質問は簡単に思えるかもしれませんが、そうです。 Dockerが存在する場合、ネットワークを処理するシステムの他の部分には常にいくつかの問題が発生します。一度nftables特にDockerが中断された後、Dockerの幅広い採用と直接使用はbr_netfilter状況をより単純化する可能性があります。

まだ使う価値があると思うならnftablesDockerの行に沿ってDockerにその部分を処理させ、単純な変更(たとえば、新しいファイアウォールを起動するなど)が行われる限り、他のファイアウォールルールでDocker設定を重複させる必要がないようにするアプローチを以下に考えました。新しい公開ポートがあるコンテナ)。

解決が必要な問題

iptablesまだ必要

現在(2021年)Dockerを引き続き使用しています。iptablesそしてただiptables(あなたも利用できますファイアウォールしかし、ただファイアウォールそしてiptables後端。とにかく私はこのシナリオを考慮しない)。したがって、現在では純粋なものを得る方法はありません。nftablesDockerを使用するときのシステム。実はiptablesそうかもiptables-legacyしれiptables-nftません。

以下は関連抜粋です。ドッカーとiptablesこの場合に便利です。

Dockerは、iptables次の2つのカスタムチェーンをインストールします。DOCKER-USERDOCKER着信パケットが常にこれら2つのチェーンによって最初に確認されるようにします。

DockerのすべてのiptablesルールがDOCKERチェーンに追加されます。。このチェーンを手動で操作しないでください。Dockerルールの前にロードされるルールを追加する必要がある場合は、DOCKER-USERチェーンに追加してください。。これらのルールは、Dockerが自動的にルールを作成する前に適用されます。

Nitpicking: 実際、Docker はこれを行うので、-A DOCKER-USER -j RETURNdocker を起動する前にルールを追加する必要があります。または、より良い方法は次のとおりです。入れるすべての場合に有効です。

FORWARDチェーンにルールが追加されます。- 手動または他のiptablesベースのファイアウォールを介して -評価を受ける後ろにこのチェーン。

DockerはチェーンのポリシーもFORWARDに設定しますDROP。 Dockerホストがルーターとしても機能している場合、そのルーターはもはやトラフィックを転送しません。

DockerはIP転送を有効にしますが、デフォルトではDocker自体以外の目的でファイアウォールで使用します。

iptablesDockerエンジンの設定ファイルでキーをfalseに設定できますが、/etc/docker/daemon.jsonこのオプションはほとんどのユーザーには適していません。Dockerがiptablesルールを生成するのを完全に防ぐことは不可能です。、事実の後に生成するのは複雑で、このガイドラインの範囲外です。 iptablesをfalseに設定すると、Dockerエンジンのコンテナネットワークが破損する可能性があります。

持つことを避けられないiptables

br_netfilter

そして、Dockerはカーネルモジュールもロードします。br_netfilterこのプロパティを設定するには:

# sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 1

だからブリッジフレーム(ここではIPv4タイプ額縁一時的にIPv4に変換データパック)フィルタリングiptables そして渡すnftables(明示的に文書化されていませんが、nftables良いiptablesNetfilter に接続すると、Netfilter はフックのソースに関係なくこれらのフックを呼び出します。iptablesまたはnftables)。

この機能は、Dockerと対話する際の問題の主な原因です。これがわからない場合は、なぜコンテナが同じ内部ブリッジLANにあるのか疑問に思います。お互いにコミュニケーションができないDockerまたはDockerが実行している他のエントリ(LXC、libvirt / QEMU ...)によって処理されなくなりました。

これは一般ネットワークのNetfilterとパケットフロー:

一般ネットワークのNetfilterとパケットフロー

一本鎖iptablesまたはnftablesしたがって、IP / INETファミリは、一般的なルーティングパス(緑色のネットワーク層フィールド内の緑色のボックス)とブリッジパス(青いリンク層のフィールド内の緑色のボックス)の2つの異なる方法でナビゲートできます。これ文書また、次のように言いました。

ブリッジされたパケットは、レイヤ1(リンクレイヤ)の上のネットワークコードには決して入りません。したがって、ブリッジされたIPパケット/フレームにはIPコードは入力されません。

これは、データパケットが通過しないことを保証する。二重同じチェーンが安心です。

間の相互作用iptablesそしてnftables

使用することが目標だからnftables一緒に使う方法を知る必要があります。

この質問に対する私の答えは次のとおりです。

結論として:

  • iptablesそしてnftables一緒に使えます
  • nftables決定論的な評価順序を持つように優先順位を指定できます。iptablesそしてnftables(この例の場合:nftables後ろにiptables)
  • これが発生するたびに、いつでもどこでもドロップされたパケットは明示的にドロップされたままになります。
  • 許可されたパケット(次のように表示されます。iptables)同じフックの次のチェーンで評価を続けます。nftables'チェーン)。
  • パケット表示を使用して、互いにメッセージを送信できます。iptablesそしてnftables

この問題を一般的な方法で解決する方法

橋路の処理

nftablesip/inet ファミリーの規則では、これを避ける必要があります。何もない橋のルートで。 Dockerを有効にしない限り、br_netfilterこの問題をまったく考慮する必要はありません。 ip/inet ファミリのブリッジパスにあるかどうかを検出するには、次の作業に従う必要があります。iptables持たないためにnftablesこれを処理し、Dockerをインストールするかどうかにかかわらず、普遍的な状態を維持します。やりやすいです。iptables比較nftablesip/inet ファミリには特定の項目があるためiptables -m physdev --physdev-is-bridgedテスト:

[!] --physdev-is-bridged

パケットがブリッジされている場合は一致します。したがって、ルーティングされません。これはFORWARDおよびPOSTROUTINGチェーンでのみ有用です。

br_netfilterこの一致は、まだ実行されていない場合はDockerによって異なり、ロードされます。br_netfilter!による問題を解決する必要があります!br_netfilter

タグを使用した接続iptablesそしてnftables

アイデアは、タグを使用してメッセージを取得することです。iptablesパスnftables、状態を区別して下さい:

  • ルール評価は、ルーティングパスではなくブリッジパスで行われます。

    いつも受け入れるそのような状況。

  • Dockerがパケットを承認しました。

    さらに制限を追加できますが、ほとんどの場合受け入れるそのような状況。

  • Dockerがパケットを無視する

    通常の使用nftablesDockerのルールについて心配しないでください。

  • 何らかの理由でパケットが廃棄されました。iptables

    意味のない出来事ですねnftablesこのパケットは表示されず、これに対して実行する必要はありません。

iptables

Dockerが起動する前に完了したら、フィルタチェーンを作成しますDOCKER-USER

iptables -N DOCKER-USER

後で完了すると、Dockerはそれを生成します。

チェーン内のDocker評価の前に、ブリッジパス検出ケースに含まれているパケットを別のマーキングとしてマークするDOCKERルールを追加します(以前のようにここに挿入しますが、ここで重要な自然順序を維持するために番号を付けます)。

iptables -I DOCKER-USER 1 -j MARK --set-mark 0xd0cca5e
iptables -I DOCKER-USER 2 -m physdev --physdev-is-bridged -j MARK --set-mark 0x10ca1

0x10ca1と0xd0cca5eはランダムに選択された値です。

DOCKER一時Docker評価タグの場合にのみパケットのタグをリセットする最終ルールを追加します(Dockerの実行前または後にDockerは常にチェーンを挿入する前に挿入するため、効果は同じです)。そしてACCEPT上書きする最後の項目を追加してください。DockerのデフォルトDROPポリシー設定FORWARDはチェーンにあります。:追加評価を遅らせようと思います。nftablesDockerに依存しないパケットに使用されます。

iptables -A FORWARD -m mark --mark 0xd0cca5e -j MARK --set-mark 0
iptables -A FORWARD -j ACCEPT

nftables

優先順位の値をinet filter forward次より少し大きい値に変更します。NF_IP_PRI_FILTER(0)(例:10)nftables順方向チェーンiptables filter/FORWARDこの年代記を尊重します。 OPルールセットのデフォルトのリンク行は、次のように変更する必要があります。

    chain forward {
            type filter hook forward priority 0; policy drop;

到着する:

      chain forward {
              type filter hook forward priority 10; policy drop;

前述の4つの条件は、次の場所で検出できます。nftables包装の印を確認してください。デバッグを支援するために式を追加しますcounter

  • タグ0x10ca1:ブリッジパス

    ブリッジパス透過トランスポートルールを追加します。

    nft add rule inet filter forward meta mark 0x10ca1 counter accept
    
  • タグ0xd0cca5e:Dockerケース

    • Docker ケースを処理するための一般/ユーザーチェーンを作成し、それを呼び出すルールを追加します。

      nft add chain inet filter dockercase
      nft add rule inet filter forward meta mark 0xd0cca5e counter jump dockercase
      
    • Dockerに関する追加の制限を追加しますが、デフォルトで許可します。

      たとえば、次から着信パケットを制限します。イノ2インターフェイスは、192.168.0.0/16 内のプライベートアドレスから来る場合にのみ許可されます。

      nft add rule inet filter dockercase iif eno2 ip saddr != 192.168.0.0/16 counter drop
      nft add rule inet filter dockercase counter accept
      
  • タグなし:Dockerとは無関係の一般的なケース

    何も含まず、デフォルト値を持つものを含め、Dockerの存在を考慮せずに実行できるアクションを追加します。減らすそうでなければ、いつもから始めることができます。ct state related,established accept

  • (パケットなし:削除済みiptables、大文字と小文字なし)

上記の例は次のとおりです。

...
    chain forward {
        type filter hook forward priority 10; policy drop;
        meta mark 0x10ca1 counter accept
        meta mark 0xd0cca5e counter jump dockercase
    }

    chain dockercase {
        iif eno2 ip saddr != 192.168.0.0/16 counter drop
        counter accept
    }
...

汎用処理の実装

ポート80と6200はnftablesもうルールはありません。 Dockerコマンドを使用して新しいポートを公開する必要がある新しいコンテナを追加する場合は、何もする必要はありません。nftables: タグ付けのため処理が完了しました。

より多くのチェーンを追加

またはbr_netfilter影響、別の根拠があるべきですか?nftablesプロパティにリンクしたり、hook forward削除hook postroutingルールを含めたり、より便利には、次に説明するトリックを使用せずにルールを変更します(当然...)。前のリンクは図7bの下にある。、同じ配列が必要です。

  • 優先順位の値は次の値より高くなければなりません。iptables'同等のチェーン優先順位

  • そんなiptables等価チェーン(filter/FORWARDですでに行われていない場合DOCKER-USER)は、次のものを受け取る必要があります。

    iptables -t foo -I BAR -m physdev --physdev-is-bridged -j MARK --set-mark 0x10ca1

    場合によっては、間、または間fooと間rawmanglenatBARPREROUTINGPOSTROUTING

  • そして最初のルールnftablesチェーンは再び次のようになります。

    meta mark 0x10ca1 accept
    
  • チェーンのポリシーが再びそうである場合は、drop以前と同様に、0xd0cca5eとマークされたルールを使用してユーザー/一般チェーンジャンプを再含める必要があります。

これに対して、hook prerouting文書には--physdev-is-bridgedこれが適用されない可能性があることが示されていますPREROUTING。絶対デフォルトの削除ポリシーを使用しないでください。とにかく、hook prerouting場合によってはまだ0xd0cca5eタグを継承できませんが、filter/FORWARD次のものを使用する場合も同様です。iptables:PREROUTING未来に何が起こるかを予測する方法はありません。

ブリッジレベルで本当に何かをしたい場合は、以下を使用してください。nftablesブリッジファミリでは、ブリッジパスから呼び出されるip / inetファミリの特別な場合には依存しないでくださいbr_netfilter

警告する

今、この問題を処理するためにマーカーを使用し、他の問題を処理するためにマーカーを使用することはより困難ですが、少し注意を払うだけでは不可能ではありません。たとえば、これらのタグでビット操作とマスクを使用します。これは次のように実行できます。iptablesそしてnftablesip ruleマーカーをセレクターとして使用してもマスクが許可されます。


重要な追加必須調整

ドッカーを追加ナットiptablesを使用したポート転送ルールDNATターゲット。最後に公開/公開されたすべてのポートはルーティング済みホストは受信せずにコンテナに渡します。これは、それらが次のものを使用することを意味します。iptablesチェーンfilter/FORWARDも同様です(OPのルールセットを使用)nftables inet filter forwardINPUTチェーンであり、/を使用しませんinput

しかも正しい接続を妨げるルールがありません所有者

inet filter input

入力パスは、以下を除いてDockerコンテナにはまったく使用されません。ドッカーエージェントこのケースは通常localhostアクセスに使用されますが、OPはすでに承認されているため、iif lo acceptこの回答ではこれ以上処理する必要はありません。 Dockerに関する情報はここにはありません。コンテナポート80および6200への参照は役に立たないため、削除する必要があります。

それからDockerに関係なく入力するチェーンが状態ルールを見逃した。これがない場合は、ホストの出力(DNSクエリ)からトラフィックが返されます。返信する、平ら返信する、アップグレードをダウンロードしています...)が失敗します。これを使用してください:

    chain input {
            type filter hook input priority 0; policy drop;
            ct state related,established accept
            iif lo accept
            iif eno2 icmp type echo-request accept
            iif eno2 ip 192.168.0.0/16 tcp dport 22 accept
            iif eno2 ip 192.168.0.0/16 tcp dport 443 accept
    }

入力パスにはまだ追加のルールが必要です。ドッカー自体(代わりにそのコンテナ):Docker API(セキュリティ上の考慮事項が許可されている場合)や使用されるVxLANなどのさまざまな機能へのリモートアクセスを許可するには、ルールが必要になる場合があります。桟橋労働者の群衆

inet filter output

同様に、OPinet filter outputチェーンの削除ポリシーはホスト接続(DNS)を終了します。お問い合わせ、平ら必要またはダウンロードを開始できません。など)。policy acceptホスト自体から出る必要なトラフィックの例外があるか追加する必要があります。チェーンには以下を含める必要があります。少なくともこのような:

  chain output {
          type filter hook output priority 0; policy drop;
          ct state related,established accept
          oif lo accept
          udp dport { 53, 123 } accept
          tcp dport { 53, 80, 443 } accept
          icmp type echo-request accept
  }

コンテナ内のパケットはこれらのチェーンによって評価されませんが、チェーンforwardによって評価され、制限されません。

IPv6

使用イントラネットICMPv6が正しく有効になっていない場合、IPv6ファミリはIPv6がARPに依存せず(ファイアウォールをほとんど使用しない)代わりに、リンクローカル接続のためにICMPv6に依存するため、すべてのIPv6接続をブロックします。家を使うかip(そして以下を除く)フィルターテーブルとの衝突を避けるためiptables-nft) または ICMPv6 を正しく処理してください。すべてを受け入れるか、正しい方向inputに必要なものを確認してください。outputSLAAC新しい民主党:RS、RA、NS、NA,...),ping...処理中です。

関連情報