私のコンピュータは、非常に厳格なnftables設定を有効にした2つのDockerコンテナを実行しています。この方法を維持したいのですが、Dockerコンテナへの外部アクセスをホワイトリストに追加します。
コンテナはポート80と6200を開きます。 dockerサービスはiptablesが無効になっている状態で開始されます。
これは私の試みを含む現在のファイアウォール構成です。icmp
、ssh
およびは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-USER
DOCKER
着信パケットが常にこれら2つのチェーンによって最初に確認されるようにします。
Dockerのすべてのiptablesルールが
DOCKER
チェーンに追加されます。。このチェーンを手動で操作しないでください。Dockerルールの前にロードされるルールを追加する必要がある場合は、DOCKER-USER
チェーンに追加してください。。これらのルールは、Dockerが自動的にルールを作成する前に適用されます。
Nitpicking: 実際、Docker はこれを行うので、-A DOCKER-USER -j RETURN
docker を起動する前にルールを追加する必要があります。または、より良い方法は次のとおりです。入れるすべての場合に有効です。
FORWARD
チェーンにルールが追加されます。- 手動または他のiptablesベースのファイアウォールを介して -評価を受ける後ろにこのチェーン。
Dockerはチェーンのポリシーも
FORWARD
に設定しますDROP
。 Dockerホストがルーターとしても機能している場合、そのルーターはもはやトラフィックを転送しません。
DockerはIP転送を有効にしますが、デフォルトではDocker自体以外の目的でファイアウォールで使用します。
iptables
Dockerエンジンの設定ファイルでキーを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とパケットフロー:
一本鎖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
と間raw
mangle
nat
BAR
PREROUTING
POSTROUTING
そして最初のルール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そしてnftables。ip rule
マーカーをセレクターとして使用してもマスクが許可されます。
重要な追加必須調整
ドッカーを追加ナットiptablesを使用したポート転送ルールDNATターゲット。最後に公開/公開されたすべてのポートはルーティング済みホストは受信せずにコンテナに渡します。これは、それらが次のものを使用することを意味します。iptablesチェーンfilter/FORWARD
も同様です(OPのルールセットを使用)nftables inet filter forward
INPUT
チェーンであり、/を使用しません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
に必要なものを確認してください。output
SLAAC(新しい民主党:RS、RA、NS、NA,...),ping...処理中です。