「Nftables」の版間の差分
編集の要約なし |
Kusanaginoturugi (トーク | 投稿記録) →参照: update |
||
| (11人の利用者による、間の30版が非表示) | |||
| 3行目: | 3行目: | ||
[[en:nftables]] |
[[en:nftables]] |
||
{{Related articles start}} |
{{Related articles start}} |
||
{{Related|ファイアウォール}} |
|||
{{Related|iptables}} |
{{Related|iptables}} |
||
{{Related|Firewalld}} |
|||
{{Related articles end}} |
{{Related articles end}} |
||
[ |
[https://netfilter.org/projects/nftables/ nftables] は既存の ip-, ip6-, arp-, ebtables フレームワークを置き換える [[Wikipedia:Netfilter|Netfilter]] のプロジェクトです。新しいパケットフィルタリングフレームワーク、新しいユーザースペースユーティリティ (nft)、そして ip- と ip6tables の互換レイヤーを提供します。現行のフック、接続追跡システム、ユーザースペースのキューイングコンポーネント、そして netfilter のログサブシステムを使っています。 |
||
最初のリリースは Linux 3.13 から使うことが可能で、このカーネルは現在 [core] リポジトリに入っています ({{Pkg|linux}})。(ユーザースペースコンポーネントの) nftables は [extra] リポジトリから利用でき ({{Pkg|nftables}})、[[Arch User Repository|AUR]] には {{AUR|nftables-git}} パッケージがあります。 |
|||
==概要== |
|||
nftables は3つのメインコンポーネントから構成されています: カーネルの実装、libnl netlink communication そして nftables ユーザースペースフロントエンド。カーネルは netlink の設定インターフェイスだけでなく、小さなクラス言語インタプリタを使用するランタイムのルールセットの評価も提供します。libnl にはカーネルと通信するためのローレベルな関数が含まれています。nftables フロントエンドはユーザーが対話するものです。 |
nftables は3つのメインコンポーネントから構成されています: カーネルの実装、libnl netlink communication そして nftables ユーザースペースフロントエンド。カーネルは netlink の設定インターフェイスだけでなく、小さなクラス言語インタプリタを使用するランタイムのルールセットの評価も提供します。libnl にはカーネルと通信するためのローレベルな関数が含まれています。nftables フロントエンドはユーザーが対話するものです。 |
||
[https://wiki.nftables.org/wiki-nftables/index.php/Main_Page nftables の公式 wiki] には詳しい情報が載っています。 |
|||
==nft== |
|||
nftables のユーザースペースユーティリティ {{ic|nft}} は現在カーネルのためにルールセットを処理する前にほとんどのルールセットの評価を行います。そのため、nftables はデフォルトのテーブルやチェインを提供していません。しかしながらユーザーが iptables のような設定をエミュレートすることが可能です。 |
|||
== インストール == |
|||
ifconfig や iproute2 と同じような感じで動作します。iptables のように引数のスイッチを使う代わりに、長く構造化された連続のコマンドになります。例えば: |
|||
nft add rule ip6 filter input ip6 saddr ::1 accept |
|||
{{ic|add}} はコマンドです。{{ic|rule}} は {{ic|add}} のサブコマンドです。{{ic|ip6}} は {{ic|rule}} の引数で、ip6 ファミリーを使うことを宣言しています。{{ic|filter}} と {{ic|input}} は {{ic|rule}} の引数で、それぞれ使用するテーブルとチェインを指定しています。残りはルールの定義で、マッチ ({{ic|ip}}) とパラメータ ({{ic|saddr}})、パラメータの引数 ({{ic|::1}}) そしてジャンプ ({{ic|accept}}) からなります。 |
|||
ユーザースペースユーティリティパッケージ {{Pkg|nftables}} を[[インストール]]してください。 |
|||
以下は nft で利用できるコマンドの不完全なリストです: |
|||
<nowiki> |
|||
list |
|||
tables [family] |
|||
table [family] <name> |
|||
chain [family] <table> <name> |
|||
{{Pkg|iptables-legacy}} がインストールされている場合は、{{Pkg|iptables}} をインストールしてください。これにより {{Pkg|iptables-legacy}} が自動的にアンインストールされ、{{Pkg|nftables}} との競合を防ぎます。 |
|||
add |
|||
table [family] <name> |
|||
chain [family] <table> <name> [chain definitions] |
|||
rule [family] <table> <chain> <rule definition> |
|||
{{Note|{{Pkg|iptables}} パッケージは、実際には nftables ルールを作成し操作する {{ic|iptables}} コマンドの実装を提供します。ただし、古い {{Pkg|iptables-legacy}} ツールで作成されたルールは別のオブジェクトであり、それらが存在する場合、''iptables'' は警告を表示します。}} |
|||
table [family] <name> (shortcut for `add table`) |
|||
=== フロントエンド === |
|||
insert |
|||
rule [family] <table> <chain> <rule definition> |
|||
{{Tip|ほとんどの [[iptables#Front-ends|iptables フロントエンド]]は nftables を直接または間接的にサポートしていませんが、将来的に対応する可能性があります。[https://www.spinics.net/lists/netfilter/msg58215.html] nftables と iptables の両方をサポートするグラフィカルフロントエンドの 1 つは [[firewalld]] です。[https://firewalld.org/2018/07/nftables-backend] [[ufw]] は互換レイヤー ''iptables-nft'' を介してサポートされています。[https://bugs.launchpad.net/ufw/+bug/1880453]}} |
|||
delete |
|||
table [family] <name> |
|||
chain [family] <table> <name> |
|||
rule [family] <table> <handle> |
|||
* {{App|[[firewalld]] (firewall-cmd)|ネットワークとファイアウォールゾーンの設定、およびファイアウォールルールの設定と構成を行うデーモンおよびコンソールインターフェイス。|https://firewalld.org/|{{Pkg|firewalld}}}} |
|||
flush |
|||
* {{App|nft-blackhole|国別およびブラックリストによって nftables で IP をブロックするスクリプト / デーモン。|https://github.com/tomasz-c/nft-blackhole|{{AUR|nft-blackhole}}}} |
|||
table [family] <name> |
|||
* {{App|[[ufw]]|Ufw は Uncomplicated Firewall の略で、netfilter ファイアウォールを管理するためのプログラムです。|https://help.ubuntu.com/community/UFW|{{Pkg|ufw}}}} |
|||
chain [family] <table> <name></nowiki> |
|||
* {{App|reaction|プログラムの出力から繰り返し出現するパターンをスキャンし、アクションを実行するデーモン。fail2ban の軽量な代替です。|https://framagit.org/ppom/reaction|{{AUR|reaction}}}} |
|||
{{ic|family}} は任意ですが、デフォルトは {{ic|ip}} になります。 |
|||
== |
== 使用方法 == |
||
テーブルの用途はチェインを保持することです。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルは指定の4つのファミリーのうちどれか一つを持つことができ、それによって様々な iptables のユーティリティを一つに統一します: |
|||
{{Tip|すでに iptables ルールがある場合は、その iptables ルールを nftables ルールに変換できます。詳しくは [https://wiki.nftables.org/wiki-nftables/index.php/Moving_from_iptables_to_nftables] を参照してください。}} |
|||
'''nftables''' は、コマンドラインで作成された一時的なルールと、ファイルから読み込まれた、またはファイルに保存された永続的なルールを'''区別しません'''。 |
|||
すべてのルールは {{ic|nft}} コマンドラインユーティリティを使って作成または読み込む必要があります。 |
|||
使用方法については [[#設定]] セクションを参照してください。 |
|||
現在の ruleset は次のコマンドで表示できます: |
|||
# nft list ruleset |
|||
すべての ruleset を削除し、システムにファイアウォールがない状態にします: |
|||
# nft flush ruleset |
|||
{{ic|nftables.service}} を[[再起動]]することで、{{ic|/etc/nftables.conf}} から ruleset を読み込みます。 |
|||
=== シンプルなファイアウォール === |
|||
{{Pkg|nftables}} には、{{ic|/etc/nftables.conf}} ファイルに保存されたシンプルで安全なファイアウォール設定が付属しています。 |
|||
{{ic|nftables.service}} は、[[起動/有効化]]されたときに、そのファイルからルールを読み込みます。 |
|||
== 設定 == |
|||
nftables ユーザースペースユーティリティ {{ic|nft}} は、ruleset をカーネルに渡す前に、ルールセット評価の大部分を実行します。ルールはチェインに格納され、チェインはテーブルに格納されます。以下のセクションでは、これらの構造を作成および変更する方法を示します。 |
|||
ファイルから入力を読み込むには、{{ic|-f}}/{{ic|--file}} オプションを使用します: |
|||
# nft --file ''filename'' |
|||
既に読み込まれているルールは'''自動的には'''フラッシュされないことに注意してください。 |
|||
すべてのコマンドの完全な一覧については {{man|8|nft}} を参照してください。 |
|||
===テーブル=== |
|||
テーブルは[[#チェイン|チェイン]]を保持します。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルの数や名前はユーザーが自由に決めることができますが、各テーブルにはアドレスファミリーをひとつしか保持することができません。5つのファミリーのうち指定したファミリーのパケットにだけ適用されます: |
|||
{| class="wikitable" |
{| class="wikitable" |
||
| 56行目: | 77行目: | ||
|- |
|- |
||
| ip6 || ip6tables |
| ip6 || ip6tables |
||
|- |
|||
| inet || iptables と ip6tables |
|||
|- |
|- |
||
| arp || arptables |
| arp || arptables |
||
| 62行目: | 85行目: | ||
|} |
|} |
||
{{ic|ip}} がデフォルトのファミリーです。 |
{{ic|ip}} (IPv4) がデフォルトのファミリーです。特に指定がなければ {{ic|ip}} が使われます。 |
||
IPv4 と IPv6 の両方に適用されるルールを作成するには {{ic|inet}} を使います。{{ic|inet}} を使うには Linux 3.15 以上が必要で、{{ic|ip}} と {{ic|ip6}} ファミリーを統一してルールを簡単に定義できます。 |
|||
{{Note|{{ic|inet}} は {{ic|nat}} タイプのチェインでは使えず、{{ic|filter}} タイプのチェインを使う必要があります ([https://www.spinics.net/lists/netfilter/msg56411.html ソース])。}} |
|||
アドレスフファミリーの完全な定義は {{man|8|nft}} の {{ic|ADDRESS FAMILIES}} セクションを参照してください。 |
|||
以下で例示しているコマンドの {{ic|''family''}} は全て任意であり、指定しなかった場合は {{ic|ip}} が使われます。 |
|||
==== テーブルの作成 ==== |
|||
以下のコマンドで新しいテーブルが追加されます: |
|||
# nft add table ''family'' ''table'' |
|||
==== テーブルの一覧表示 ==== |
|||
全てのテーブルを表示するには: |
|||
===表示=== |
|||
ファミリーの現在のテーブルは {{ic|nft list}} コマンドで一覧できます。 |
|||
# nft list tables |
# nft list tables |
||
# nft list tables ip6 |
|||
テーブルの |
==== テーブル内のチェインとルールの表示 ==== |
||
# nft list table foo |
|||
# nft list table ip6 foo |
|||
指定したテーブルの全てのチェインとルールを表示するには: |
|||
===作成=== |
|||
テーブルは2つのコマンド (片方はもう片方のショートカットです) で追加することができます。以下は foo という名前の ip テーブルと foo という名前の ip6 テーブルを追加する例です: |
|||
# nft add table foo |
|||
# nft table ip6 foo |
|||
ファミリーが異なっていれば同じ名前のテーブルを作ることが可能です。 |
|||
# nft list table ''family_type'' ''table_name'' |
|||
===削除=== |
|||
テーブルを削除することができるのはチェインが存在しない場合だけです。 |
|||
# nft delete table foo |
|||
# nft delete table ip6 foo |
|||
例えば、{{ic|inet}} family の {{ic|my_table}} テーブルのすべてのルールを一覧表示するには: |
|||
==チェイン== |
|||
チェインの用途はルールを保持することです。iptables のチェインと違って、nftables には初めから組み込まれているチェインはありません。そのためチェインが netfilter フレームワークにあるタイプやフックをどれも使わない場合、iptables とは異なりチェインを通り抜けるパケットは nftables の影響を受けません。 |
|||
# nft list table inet my_table |
|||
===表示=== |
|||
{{ic|nft list table foo}} コマンドは foo テーブルの全てのチェインを表示します。個々のチェインからルールを一覧することもできます。 |
|||
# nft list chain foo bar |
|||
# nft list chain ip6 foo bar |
|||
上記コマンドは ip と ip6 の {{ic|foo}} テーブルの {{ic|bar}} チェインを表示します。 |
|||
==== テーブルの削除 ==== |
|||
===作成=== |
|||
テーブルがファイル定義や {{ic|nft add chain}} コマンドによって作成されたら、チェインを追加することができます。 |
|||
# nft add chain foo bar |
|||
# nft add chain ip6 foo bar |
|||
上記コマンドは {{ic|bar}} という名前のチェインを ip と ip6 の {{ic|foo}} テーブルに追加します。 |
|||
テーブルを削除するには: |
|||
====プロパティ==== |
|||
nftables には組み込みチェインが存在しないため、チェインは netfilter フレームワークの特定の機能にアクセスすることができます。 |
|||
# nft add chain filter input { type filter hook input priority 0\; } |
|||
上記コマンドは nftables に {{ic|input}} という名前のチェインを {{ic|filter}} テーブルに追加させ、そのタイプ・フック・プライオリティを定義します。これらのプロパティは基本的に iptables で組み込まれているテーブルやチェインを置き換えるものです。 |
|||
# nft delete table ''family_type'' ''table_name'' |
|||
=====タイプ===== |
|||
チェインには3つのタイプがあり、iptables で使われているテーブルと対応しています: |
|||
*filter |
|||
*nat |
|||
*route (mangle) |
|||
これにより、テーブル内のすべてのチェインが破棄されます。 |
|||
=====フック===== |
|||
チェインは5つのフックを使うことができ、iptables で使われているチェインと対応しています: |
|||
*input |
|||
*output |
|||
*forward |
|||
*prerouting |
|||
*postrouting |
|||
==== |
==== テーブルのクリア ==== |
||
{{Note|Priorities do not currently appear to have any effect on which chain sees packets first.}} |
|||
{{Note|Since the priority seems to be an unsigned integer, negative priorities will be converted into very high priorities.}} |
|||
プライオリティは nftables がどのパケットを初めに通過させるかを示します。整数で指定し、高い値を与えるほど優先されます。 |
|||
テーブルから全てのルールを消去するには: |
|||
===削除=== |
|||
チェインはルールが存在しない場合にのみ削除することができます。 |
|||
# nft delete chain foo bar |
|||
# nft delete chain ip6 foo bar |
|||
以上のコマンドは ip と ip6 の {{ic|foo}} テーブルから {{ic|bar}} チェインを削除します。 |
|||
# nft flush table ''family_type'' ''table_name'' |
|||
==ルール== |
|||
ルールの用途はパケットを識別(マッチ)して処理を実行(ジャンプ)することです。iptables と同じように、様々なマッチやジャンプが利用できますが、nftables には欠けている機能も存在します。 |
|||
=== |
===チェイン=== |
||
テーブルを表示するのと同じ方法を使って、{{ic|nft list}} コマンドでテーブルの中の現在のルールを表示することができます。個別のチェインからルールを表示することも可能です。 |
|||
# nft list chain foo bar |
|||
# nft list chain ip6 foo bar |
|||
These commands will list the rules in the {{ic|bar}} chains in the ip and ip6 {{ic|foo}} tables. |
|||
チェインの用途は[[#ルール|ルール]]を保持することです。iptables のチェインと違って、nftables には初めから組み込まれているチェインはありません。そのためチェインが netfilter フレームワークにあるタイプやフックをどれも使わない場合、iptables とは異なりチェインを通り抜けるパケットは nftables の影響を受けません。 |
|||
===作成=== |
|||
テーブルがファイル定義や {{ic|nft add rule}} コマンドによって作成されたら、ルールを追加することができます。 |
|||
# nft add rule foo bar ip saddr 127.0.0.1 accept |
|||
# nft add rule ip6 foo bar ip saddr ::1 accept |
|||
These commands will add a rule to the {{ic|bar}} chains in the ip and ip6 {{ic|foo}} tables that matches an {{ic|ip}} packet when its {{ic|saddr}} (source address) is 127.0.0.1 (IPv4) or ::1 (IPv6) and accepts those packets. |
|||
チェインには2つのタイプがあります。''base'' チェインはネットワークスタックからのパケットのエントリポイントとなります。フックの値を指定することができます。''regular'' チェインはジャンプターゲットとして使用することができます。 |
|||
====マッチ==== |
|||
There are various matches available in nftables and, for the most part, coincide with their iptables counterparts. The most noticeable difference is that there are no generic or implicit matches anymore. A generic match was one that was always available, such as {{ic|--protocol}} or {{ic|--source}}. Implicit matches were protocol-specific, such as {{ic|--sport}} when a packet was determined to be TCP. |
|||
以下のコマンドで使っている {{ic|''family_type''}} は全て任意であり、指定しなかった場合は {{ic|ip}} が使われます。 |
|||
The following is an incomplete list of the matches available: |
|||
*meta (meta properties, e.g. interfaces) |
|||
*icmp (ICMP protocol) |
|||
*icmpv6 (ICMPv6 protocol) |
|||
*ip (IP protocol) |
|||
*ip6 (IPv6 protocol) |
|||
*tcp (TCP protocol) |
|||
*udp (UDP protocol) |
|||
*sctp (SCTP protocol) |
|||
*ct (connection tracking) |
|||
==== チェインの作成 ==== |
|||
The following is an incomplete list of match arguments: |
|||
===== Base chain ===== |
|||
base chain を追加するには、type、hook、priority の値を指定する必要があります: |
|||
# nft add chain ''family_type'' ''table_name'' ''chain_name'' '{ type ''chain_type'' hook ''hook_type'' priority ''priority_value'' ; policy ''policy'' ;}' |
|||
{{ic|''chain_type''}} には {{ic|filter}}、{{ic|route}}、{{ic|nat}} を指定できます。 |
|||
IPv4/IPv6/Inet address family では、{{ic|''hook_type''}} に {{ic|prerouting}}、{{ic|input}}、{{ic|forward}}、{{ic|output}}、{{ic|postrouting}} を指定できます。サポートされる ''family_type''、''chain_type''、''hook_type'' の組み合わせ一覧については {{man|8|nft|CHAINS}} を参照してください。 |
|||
{{ic|''priority_value''}} には priority 名または整数値を指定できます。標準 priority 名と値の一覧については {{man|8|nft|CHAINS}} を参照してください。数値が小さいチェインほど先に処理され、負の値も使用できます。[https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_types] |
|||
任意で、base chain には {{ic|''policy''}} ({{ic|drop}} またはデフォルトの {{ic|accept}}) を指定できます。これにより、チェイン内のルールで明示的に accept または refuse されなかったパケットに何が起こるかを定義します。 |
|||
例えば、入力パケットをフィルタリングする base chain を追加するには: |
|||
# nft add chain inet my_table my_chain '{ type filter hook input priority 0; }' |
|||
上記のいずれでも {{ic|add}} を {{ic|create}} に置き換えると、新しいチェインを追加しますが、チェインが既に存在する場合はエラーを返します。 |
|||
===== Regular chain ===== |
|||
次のコマンドは、{{ic|''table_name''}} という名前のテーブルに {{ic|''chain_name''}} という名前の regular chain を追加します: |
|||
# nft add chain ''family_type'' ''table_name'' ''chain_name'' |
|||
例えば、{{ic|inet}} address family の {{ic|my_table}} テーブルに {{ic|my_tcp_chain}} という regular chain を追加するには: |
|||
# nft add chain inet my_table my_tcp_chain |
|||
==== チェインの一覧表示 ==== |
|||
次のコマンドは、''family_type'' のすべてのチェインを、ルールなしで一覧表示します ([[#ルールの一覧表示]] を参照): |
|||
# nft list chains ''family_type'' |
|||
例えば、次のコマンドは IPv6 のチェインを一覧表示します: |
|||
# nft list chains ip6 |
|||
family_type を省略した場合、すべてのチェインが表示されます。 |
|||
==== チェインの編集 ==== |
|||
チェインを編集したいときは、チェインの名前を指定して変更したいルールを定義します: |
|||
# nft chain ''family_type table_name chain_name'' '{ [ type ''chain_type'' hook ''hook_type'' device ''device_name'' priority ''priority_value'' ; policy ''policy_type'' ; ] }' |
|||
例えば、デフォルトテーブル内の {{ic|my_input}} チェインの policy を {{ic|accept}} から {{ic|drop}} に変更するには: |
|||
# nft chain inet my_table my_input '{ policy drop ; }' |
|||
==== チェインの削除 ==== |
|||
チェインを削除するには: |
|||
# nft delete chain ''family_type'' ''table_name'' ''chain_name'' |
|||
削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。 |
|||
==== チェインのルールを消去 ==== |
|||
チェインからルールを消去するには: |
|||
# nft flush chain ''family_type'' ''table_name'' ''chain_name'' |
|||
=== ルール === |
|||
ルールは表現または宣言から構成され、チェインの中に格納されます。 |
|||
==== ルールの追加 ==== |
|||
{{Tip|''iptables-translate'' ユーティリティを使うことで [[iptables]] のルールを nftables フォーマットに変換できます。}} |
|||
チェインにルールを追加するには: |
|||
# nft add rule ''family_type'' ''table_name'' ''chain_name'' handle ''handle_value'' ''statement'' |
|||
ルールは {{ic|''handle_value''}} の位置に追加されます。これは任意です。指定しない場合、ルールはチェインの末尾に追加されます。 |
|||
ルール handle を確認するには、任意の有効な list コマンドに {{ic|--handle}} スイッチを追加する必要があります。このスイッチにより、{{ic|nft}} は出力に handle を表示します。{{ic|--numeric}} 引数は、未解決の IP アドレスなど、一部の数値出力を確認するのに便利です。 |
|||
{{hc|# nft --handle --numeric list chain inet my_table my_input|2=<nowiki> |
|||
table inet my_table { |
|||
chain input { |
|||
type filter hook input priority 0; |
|||
ip saddr 127.0.0.1 accept # handle 10 |
|||
} |
|||
} |
|||
</nowiki>}} |
|||
指定位置の前にルールを挿入するには: |
|||
# nft insert rule ''family_type'' ''table_name'' ''chain_name'' handle ''handle_value'' ''statement'' |
|||
{{ic|''handle_value''}} が指定されていない場合、ルールはチェインの先頭に挿入されます。 |
|||
===== 表現 ===== |
|||
{{ic|''statement''}} にはマッチする表現と判断宣言が入ります。判断宣言には {{ic|accept}}, {{ic|drop}}, {{ic|queue}}, {{ic|continue}}, {{ic|return}}, {{ic|jump ''chain''}}, {{ic|goto ''chain''}} などが存在します。判断宣言以外の宣言も指定できます。詳しくは {{man|8|nft}} を参照してください。 |
|||
nftables では様々な表現を使うことができ、ほとんどは、iptables と対応するようになっています。一番大きな違いは汎用的なマッチと暗黙的なマッチが存在しないことです。汎用的なマッチとは、{{ic|--protocol}} や {{ic|--source}} のように、いつでも使うことができるマッチで、暗黙的なマッチとは、{{ic|--sport}} のように、特定のプロトコルでしか使えないマッチのことです。 |
|||
以下は利用できるマッチの一部です: |
|||
* meta (メタプロパティ。例: インターフェイス) |
|||
* icmp (ICMP プロトコル) |
|||
* icmpv6 (ICMPv6 プロトコル) |
|||
* ip (IP プロトコル) |
|||
* ip6 (IPv6 プロトコル) |
|||
* tcp (TCP プロトコル) |
|||
* udp (UDP プロトコル) |
|||
* sctp (SCTP プロトコル) |
|||
* ct (接続のトラッキング) |
|||
以下はマッチ引数の一部です (完全なリストは {{man|8|nft}} を見て下さい): |
|||
<nowiki> |
<nowiki> |
||
meta: |
meta: |
||
| 199行目: | 297行目: | ||
state <new | established | related | invalid></nowiki> |
state <new | established | related | invalid></nowiki> |
||
ある意味では、iif と oif に対する iifname と oifname の違いは、static と dynamic の違いに似ています。または、プログラミング概念でいう definition と declaration、あるいは early binding と delayed binding に似ています。使用例と追加説明へのリンクについては [https://serverfault.com/questions/1059391/nftables-error-interface-does-not-exist-after-reboot] を参照してください。 |
|||
====ジャンプ==== |
|||
ジャンプは iptables と同じように使うことができますが、ひとつのルールで複数のジャンプを使用できるようになっています。 |
|||
# nft add rule filter input tcp dport 22 log accept |
|||
==== ルールの一覧表示 ==== |
|||
以下はジャンプの未完成なリストです: |
|||
*accept (accept a packet) |
|||
*reject (reject a packet) |
|||
*drop (drop a packet) |
|||
*snat (perform source NAT on a packet) |
|||
*dnat (perform destination NAT on a packet) |
|||
*log (log a packet) |
|||
*counter (keep a counter on a packet; counters are optional in nftables) |
|||
*return (stop traversing the chain) |
|||
次のコマンドはチェイン内のすべてのルールを一覧表示します: |
|||
===挿入=== |
|||
{{ic|nft insert rule}} コマンドでチェインにルールを挿入することができます。 |
|||
# nft insert rule filter input ct state established,related accept |
|||
# nft list chain ''family_type'' ''table_name'' ''chain_name'' |
|||
===削除=== |
|||
Individual rules can only be deleted by their handles. The {{ic|nft --handle list}} command must be used to determine rule handles. Note the {{ic|--handle}} switch, which tells {{ic|nft}} to list handles in its output. |
|||
例えば、{{ic|my_table}} という {{ic|inet}} テーブル内の {{ic|my_output}} というチェインのルールを一覧表示するには: |
|||
The following determines the handle for a rule and then deletes it. The {{ic|--number}} argument is useful for viewing some numeric output, like unresolved IP addresses. |
|||
{{hc|# nft --handle --numeric list chain filter input|2= |
|||
# nft list chain inet my_table my_output |
|||
<nowiki> |
|||
table ip filter { |
|||
====削除==== |
|||
個々のルールはハンドルを使わないと削除することができません。{{ic|nft --handle list}} コマンドを使うことでルールのハンドルを確認できます。例えば次のような場合: |
|||
{{hc|# nft --handle --numeric list chain inet my_table my_input|2=<nowiki> |
|||
table inet my_table { |
|||
chain input { |
chain input { |
||
type filter hook input priority 0; |
type filter hook input priority 0; |
||
| 229行目: | 320行目: | ||
} |
} |
||
} |
} |
||
</nowiki> |
</nowiki>}} |
||
}} |
|||
# nft delete rule filter input handle 10 |
|||
次のコマンドで削除できます: |
|||
All the chains in a table can be flushed with the {{ic|nft flush table}} command. Individual chains can be flushed using either the {{ic|nft flush chain}} or {{ic|nft delete rule}} commands. |
|||
# nft flush table foo |
|||
# nft delete rule inet my_table my_input handle 10 |
|||
# nft flush chain foo bar |
|||
# nft delete rule ip6 foo bar |
|||
テーブル内のすべてのチェインは {{ic|nft flush table}} コマンドでフラッシュできます。個別のチェインは {{ic|nft flush chain}} または {{ic|nft delete rule}} コマンドでフラッシュできます。 |
|||
The first command flushes all of the chains in the ip {{ic|foo}} table. The second flushes the {{ic|bar}} chain in the ip {{ic|foo}} table. The third deletes all of the rules in {{ic|bar}} chain in the ip6 {{ic|foo}} table. |
|||
# nft flush table ''table_name'' |
|||
# nft flush chain ''family_type'' ''table_name'' ''chain_name'' |
|||
# nft delete rule ''family_type'' ''table_name'' ''chain_name'' |
|||
最初のコマンドは、ip {{ic|''table_name''}} テーブル内のすべてのチェインをフラッシュします。2 番目のコマンドは、{{ic|''family_type''}} {{ic|''table_name''}} テーブル内の {{ic|''chain_name''}} チェインをフラッシュします。3 番目のコマンドは、{{ic|''family_type''}} {{ic|''table_name''}} テーブル内の {{ic|''chain_name''}} チェインのすべてのルールを削除します。 |
|||
=== セット === |
|||
[https://wiki.nftables.org/wiki-nftables/index.php/Sets セットには名前付きセットと匿名セットがあります]。セットは 1 つ以上の要素で構成され、要素はカンマで区切られ、波括弧で囲まれます。匿名セットはルールに埋め込まれ、更新できません。ルールを削除して再追加する必要があります。例えば、次の dports セットから "http" だけを削除することはできません: |
|||
# nft add rule ip6 filter input tcp dport {telnet, http, https} accept |
|||
名前付きセットは更新でき、型付けやフラグ付けが可能です。''sshguard'' は、ブロックされたホストの IP アドレスに名前付きセットを使用します。 |
|||
table ip sshguard { |
|||
set attackers { |
|||
type ipv4_addr |
|||
flags interval |
|||
elements = { 1.2.3.4 } |
|||
} |
|||
セットに要素を''追加''または''削除''するには、次のようにします: |
|||
# nft add element ip sshguard attackers { 5.6.7.8/32 } |
|||
# nft delete element ip sshguard attackers { 1.2.3.4/32 } |
|||
''ipv4_addr'' 型には CIDR netmask を含められることに注意してください (ここでの {{ic|/32}} は必須ではありませんが、完全性のために含めています)。また、ここで {{ic|TABLE ip sshguard { SET attackers }<nowiki/>}} によって定義されたセットは、{{ic|ip sshguard attackers}} として参照されることにも注意してください。 |
|||
{{Tip|[[systemd-networkd]] 接続は、事前定義された名前付きセットにホスト IP アドレス、ネットワークプレフィックス、インターフェイスインデックスを投入するように設定できます。詳しくは {{man|5|systemd.network|[ADDRESS] SECTION OPTIONS}} の {{ic|NFTSet{{=}}}} の説明と [[#systemd-networkd を使った動的名前付きセット]] の例を参照してください。}} |
|||
===アトミックリロード=== |
|||
現在のルールセットをフラッシュする: |
|||
# echo "flush ruleset" > /tmp/nftables |
|||
現在のルールセットをダンプする: |
|||
# nft list ruleset >> /tmp/nftables |
|||
{{ic|/tmp/nftables}} を編集して次のコマンドで変更を適用: |
|||
# nft -f /tmp/nftables |
|||
== サンプル == |
|||
=== ワークステーション === |
|||
{{hc|/etc/nftables.conf|2=<nowiki> |
|||
flush ruleset |
|||
table inet my_table { |
|||
set LANv4 { |
|||
type ipv4_addr |
|||
flags interval |
|||
elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 } |
|||
} |
|||
set LANv6 { |
|||
type ipv6_addr |
|||
flags interval |
|||
elements = { fd00::/8, fe80::/10 } |
|||
} |
|||
chain my_input_lan { |
|||
udp sport 1900 udp dport >= 1024 meta pkttype unicast limit rate 4/second burst 20 packets accept comment "Accept UPnP IGD port mapping reply" |
|||
udp sport netbios-ns udp dport >= 1024 meta pkttype unicast accept comment "Accept Samba Workgroup browsing replies" |
|||
} |
|||
chain my_input { |
|||
type filter hook input priority filter; policy drop; |
|||
iif lo accept comment "Accept any localhost traffic" |
|||
ct state invalid drop comment "Drop invalid connections" |
|||
fib daddr . iif type != { local, broadcast, multicast } drop comment "Drop packets if the destination IP address is not configured on the incoming interface (strong host model)" |
|||
ct state { established, related } accept comment "Accept traffic originated from us" |
|||
meta l4proto { icmp, ipv6-icmp } accept comment "Accept ICMP" |
|||
ip protocol igmp accept comment "Accept IGMP" |
|||
udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS" |
|||
udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS" |
|||
ip6 saddr @LANv6 jump my_input_lan comment "Connections from private IP address ranges" |
|||
ip saddr @LANv4 jump my_input_lan comment "Connections from private IP address ranges" |
|||
counter comment "Count any other traffic" |
|||
} |
|||
chain my_forward { |
|||
type filter hook forward priority filter; policy drop; |
|||
# Drop everything forwarded to us. We do not forward. That is routers job. |
|||
} |
|||
chain my_output { |
|||
type filter hook output priority filter; policy accept; |
|||
# Accept every outbound connection |
|||
} |
|||
==ファイル定義== |
|||
{{Warning|[http://people.netfilter.org/wiki-nftables/index.php/Atomic_rule_replacement netfilter wiki] に書かれていることとは違って、{{ic|nft -f}} コマンドは'''アトミックではありません'''。そのため古いテーブルを削除するのと新しいルールセットをロードする間に、全てのパケットを許可する必要があります。}} |
|||
{{Note|{{ic|nft -f}} コマンドは使う前に衝突するテーブルを全て削除する必要があります。}} |
|||
{{ic|nft -f}} コマンドでファイル定義を利用することができます。このコマンドは {{ic|iptables-restore}} コマンドと同じように動作します。 |
|||
{{hc|/etc/nftables/filter.rules|2= |
|||
<nowiki> |
|||
table ip filter { |
|||
chain input { |
|||
type filter hook input priority 0; |
|||
ct state established,related accept |
|||
ip saddr 127.0.0.1 accept |
|||
tcp dport 22 log accept |
|||
reject |
|||
} |
|||
} |
} |
||
</nowiki> |
</nowiki>}} |
||
}} |
|||
{{Tip|[[systemd-networkd]] を使用していてローカルネットワークに接続している場合、{{man|5|systemd.network}} オプション {{ic|NFTSet{{=}}}} を使って接続のネットワークプレフィックスを取得することで、ネットワークサブネットのハードコーディングを避けられます。[[#systemd-networkd を使った動的名前付きセット]] を参照してください。}} |
|||
==はじめに== |
|||
[[iptables|iptables]] のようなチェインを設定するには、まず備え付けの IPv4 フィルターファイルを使う必要があります: |
|||
=== サーバー === |
|||
# nft -f /etc/nftables/ipv4-filter |
|||
{{hc|/etc/nftables.conf|2=<nowiki> |
|||
作成されたチェインを表示するには: |
|||
flush ruleset |
|||
table inet my_table { |
|||
# nft list table filter |
|||
set LANv4 { |
|||
type ipv4_addr |
|||
flags interval |
|||
elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 } |
|||
Drop output to a destination: |
|||
} |
|||
set LANv6 { |
|||
type ipv6_addr |
|||
flags interval |
|||
elements = { fd00::/8, fe80::/10 } |
|||
# nft add rule ip filter output ip daddr 1.2.3.4 drop |
|||
} |
|||
chain my_input_lan { |
|||
Drop packets destined for local port 80: |
|||
meta l4proto { tcp, udp } th dport 2049 accept comment "Accept NFS" |
|||
udp dport netbios-ns accept comment "Accept NetBIOS Name Service (nmbd)" |
|||
# nft add rule ip filter input tcp dport 80 drop |
|||
udp dport netbios-dgm accept comment "Accept NetBIOS Datagram Service (nmbd)" |
|||
tcp dport netbios-ssn accept comment "Accept NetBIOS Session Service (smbd)" |
|||
tcp dport microsoft-ds accept comment "Accept Microsoft Directory Service (smbd)" |
|||
udp sport { bootpc, 4011 } udp dport { bootps, 4011 } accept comment "Accept PXE" |
|||
Delete all rules in a chain: |
|||
udp dport tftp accept comment "Accept TFTP" |
|||
} |
|||
chain my_input { |
|||
# nft delete rule filter output |
|||
type filter hook input priority filter; policy drop; |
|||
iif lo accept comment "Accept any localhost traffic" |
|||
==サンプル== |
|||
ct state invalid drop comment "Drop invalid connections" |
|||
===シンプルな IP/IPv6 ファイアウォール=== |
|||
fib daddr . iif type != { local, broadcast, multicast } drop comment "Drop packets if the destination IP address is not configured on the incoming interface (strong host model)" |
|||
{{hc|firewall.rules|2= |
|||
ct state { established, related } accept comment "Accept traffic originated from us" |
|||
<nowiki> |
|||
# A simple firewall |
|||
meta l4proto { icmp, ipv6-icmp } accept comment "Accept ICMP" |
|||
table firewall { |
|||
ip protocol igmp accept comment "Accept IGMP" |
|||
chain incoming { |
|||
type filter hook input priority 0; |
|||
udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS" |
|||
# established/related connections |
|||
udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS" |
|||
ct state {established, related} accept |
|||
ip6 saddr @LANv6 jump my_input_lan comment "Connections from private IP address ranges" |
|||
# invalid connections |
|||
ip saddr @LANv4 jump my_input_lan comment "Connections from private IP address ranges" |
|||
ct state invalid drop |
|||
tcp dport ssh accept comment "Accept SSH on port 22" |
|||
# loopback interface |
|||
iifname lo accept |
|||
tcp dport ipp accept comment "Accept IPP/IPPS on port 631" |
|||
# icmp |
|||
ip protocol icmp accept |
|||
meta l4proto { tcp, udp } th dport { http, https, 8008, 8080 } accept comment "Accept HTTP (ports 80, 443, 8008, 8080)" |
|||
# open tcp ports: sshd (22), httpd (80) |
|||
tcp dport {ssh, http} accept |
|||
udp sport bootpc udp dport bootps ip saddr 0.0.0.0 ip daddr 255.255.255.255 accept comment "Accept DHCPDISCOVER (for DHCP-Proxy)" |
|||
} |
|||
chain my_forward { |
|||
type filter hook forward priority filter; policy drop; |
|||
# Drop everything forwarded to us. We do not forward. That is routers job. |
|||
} |
|||
chain my_output { |
|||
type filter hook output priority filter; policy accept; |
|||
# Accept every outbound connection |
|||
} |
|||
# everything else |
|||
reject |
|||
} |
|||
} |
} |
||
</nowiki>}} |
|||
=== レート制限 === |
|||
table ip6 firewall { |
|||
chain incoming { |
|||
type filter hook input priority 0; |
|||
{{bc|1=<nowiki> |
|||
# established/related connections |
|||
table inet my_table { |
|||
ct state {established, related} accept |
|||
chain my_input { |
|||
type filter hook input priority filter; policy drop; |
|||
iif lo accept comment "Accept any localhost traffic" |
|||
# invalid connections |
|||
ct state invalid drop comment "Drop invalid connections" |
|||
fib daddr . iif type != { local, broadcast, multicast } drop comment "Drop packets if the destination IP address is not configured on the incoming interface (strong host model)" |
|||
meta l4proto icmp icmp type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods" |
|||
# loopback interface |
|||
meta l4proto ipv6-icmp icmpv6 type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods" |
|||
iifname lo accept |
|||
ct state { established, related } accept comment "Accept traffic originated from us" |
|||
# icmp |
|||
ip6 nexthdr icmpv6 accept |
|||
meta l4proto { icmp, ipv6-icmp } accept comment "Accept ICMP" |
|||
# open tcp ports: sshd (22), httpd (80) |
|||
ip protocol igmp accept comment "Accept IGMP" |
|||
tcp dport {ssh, http} accept |
|||
tcp dport ssh ct state new limit rate 15/minute accept comment "Avoid brute force on SSH" |
|||
# everything else |
|||
reject |
|||
} |
|||
} |
|||
</nowiki>}} |
|||
===ジャンプ=== |
|||
設定ファイルでジャンプを使うときは、先にターゲットチェインを定義する必要があります。そうしないと {{ic|Error: Could not process rule: No such file or directory}} というエラーが発生します。 |
|||
{{bc|1=<nowiki> |
|||
table inet my_table { |
|||
chain web { |
|||
tcp dport http accept |
|||
tcp dport 8080 accept |
|||
} |
|||
chain my_input { |
|||
type filter hook input priority filter; |
|||
ip saddr 10.0.2.0/24 jump web |
|||
drop |
|||
} |
|||
} |
|||
</nowiki>}} |
|||
=== インターフェイスによってルールを変える === |
|||
複数のネットワークインターフェイスが存在する場合、それぞれのインターフェイスごとに別々のフィルターチェインを設定したい場合があるかもしれません。例えば、ホームルーターを構築するとき、LAN 上でアクセスできるウェブサーバーを実行しつつ ({{ic|nsp3s0}} インターフェイス)、インターネットからはアクセスできないようにしたい場合 ({{ic|enp2s0}} インターフェイス) などは以下のように設定します: |
|||
{{bc|<nowiki> |
|||
table inet my_table { |
|||
chain my_input { # this chain serves as a dispatcher |
|||
type filter hook input priority filter; policy drop; |
|||
iif lo accept comment "always accept loopback" |
|||
iifname enp2s0 jump my_input_public |
|||
iifname enp3s0 jump my_input_private |
|||
} |
|||
chain my_input_public { # rules applicable to public interface interface |
|||
ct state {established,related} accept |
|||
ct state invalid drop |
|||
udp dport bootpc accept |
|||
tcp dport bootpc accept |
|||
} |
|||
chain my_input_private { |
|||
ct state {established,related} accept |
|||
ct state invalid drop |
|||
udp dport bootpc accept |
|||
tcp dport bootpc accept |
|||
tcp port http accept |
|||
tcp port https accept |
|||
reject with icmpx port-unreachable comment "all other traffic" |
|||
} |
|||
chain my_output { # we let everything out |
|||
type filter hook output priority filter; |
|||
accept |
|||
} |
} |
||
} |
} |
||
</nowiki> |
</nowiki>}} |
||
}} |
|||
あるいは、単一の upstream interface に対する {{ic|iifname}} statement だけを選び、それ以外のすべてのインターフェイスに対するデフォルトルールを 1 か所に置くこともできます。各インターフェイスごとに dispatch する必要はありません。 |
|||
===Limit rate と tcp flags の IP/IPv6 ファイアウォール=== |
|||
{{hc|firewall.2.rules|2= |
|||
<nowiki> |
|||
table firewall { |
|||
chain incoming { |
|||
type filter hook input priority 0; |
|||
=== マスカレード === |
|||
# bad tcp -> avoid network scanning: |
|||
tcp flags & (fin|syn) == (fin|syn) drop |
|||
tcp flags & (syn|rst) == (syn|rst) drop |
|||
tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) drop # == 0 would be better, not supported yet. |
|||
tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) drop |
|||
nftables には特殊なキーワード {{ic|masquerade}} が存在し、送信元アドレスが自動的に出力インターフェイスのアドレスに設定されます ([http://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_%28NAT%29#Masquerading ソース])。ルーターのインターフェイスが多数の ISP に接続されているときなど、インターフェイスの IP アドレスが一定でない場合に有用です。通常は、インターフェイスの IP アドレスが変わるたびにネットワークアドレス変換 (NAT) のルールを更新する必要があります。 |
|||
# no ping floods: |
|||
ip protocol icmp limit rate 10/second accept |
|||
ip protocol icmp drop |
|||
{{ic|masquerade}} を使用するには: |
|||
ct state {established, related} accept |
|||
ct state invalid drop |
|||
iifname lo accept |
|||
* masquerading がカーネルで有効になっていることを確認してください (デフォルトカーネルを使用している場合は true です)。そうでない場合は、カーネル設定で {{ic|1=CONFIG_NFT_MASQ=m}} を設定します。 |
|||
# avoid brute force on ssh: |
|||
* {{ic|masquerade}} キーワードは {{ic|nat}} type のチェインでのみ使用できます。 |
|||
tcp dport {ssh} limit rate 15/minute accept |
|||
* masquerading は source NAT の一種であるため、output path でのみ動作します。 |
|||
2 つのインターフェイスを持つマシンの例です: LAN は {{ic|enp3s0}} に接続され、public internet は {{ic|enp2s0}} に接続されています: |
|||
reject |
|||
} |
|||
{{bc|<nowiki> |
|||
table inet my_nat { |
|||
chain my_masquerade { |
|||
type nat hook postrouting priority srcnat; |
|||
oifname "enp2s0" masquerade |
|||
} |
|||
} |
} |
||
</nowiki>}} |
|||
テーブル type が {{ic|inet}} なので、IPv4 と IPv6 の両方のパケットが masquerade されます。IPv6 は追加の address space により NAT が不要なため、IPv4 パケットだけを masquerade したい場合は、{{ic|meta nfproto ipv4}} expression を {{ic|oifname "enp2s0"}} の前に使用するか、テーブル type を {{ic|ip}} に変更します。 |
|||
table ip6 firewall { |
|||
chain incoming { |
|||
type filter hook input priority 0; |
|||
=== NAT とポートフォワーディング === |
|||
# bad tcp: |
|||
tcp flags & (fin|syn) == (fin|syn) drop |
|||
tcp flags & (syn|rst) == (syn|rst) drop |
|||
tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) drop # == 0 would be better, not supported yet. |
|||
tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) drop |
|||
この例では、eth0 という WAN インターフェイスを通って出ていくトラフィックを masquerade し、ポート 22 と 80 を {{ic|10.0.0.2}} に転送します。[[sysctl]] によって {{ic|net.ipv4.ip_forward}} を {{ic|1}} に設定する必要があります。 |
|||
# no ping floods: |
|||
ip6 nexthdr icmpv6 limit rate 10/second accept |
|||
ip6 nexthdr icmpv6 drop |
|||
{{bc| |
|||
ct state {established, related} accept |
|||
table nat { |
|||
ct state invalid drop |
|||
chain prerouting { |
|||
type nat hook prerouting priority dstnat; |
|||
iif eth0 tcp dport {22, 80} dnat to 10.0.0.2 |
|||
} |
|||
chain postrouting { |
|||
type nat hook postrouting priority srcnat; |
|||
oif eth0 masquerade |
|||
} |
|||
} |
|||
}} |
|||
=== IP ごとの新規接続数をカウント === |
|||
# loopback interface |
|||
iifname lo accept |
|||
HTTPS 接続をカウントするには、次のスニペットを使用します: |
|||
# avoid brute force on ssh: |
|||
tcp dport {ssh} limit rate 15/minute accept |
|||
{{hc|/etc/nftables.conf| |
|||
table inet filter { |
|||
set https { |
|||
type ipv4_addr; |
|||
flags dynamic; |
|||
size 65536; |
|||
timeout 60m; |
|||
} |
|||
chain input { |
|||
type filter hook input priority filter; |
|||
ct state new meta l4proto { tcp, udp } th dport 443 update @https { ip saddr counter } |
|||
} |
} |
||
} |
} |
||
</nowiki> |
|||
}} |
}} |
||
カウンターを表示するには、{{ic|nft list set inet filter https}} を実行してください。 |
|||
===Priority-based Atomic Fix=== |
|||
If priorities ever actually take effect, this may be a workaround for {{ic|nft -f}}'s lack of true atomicness (being able to replace all the current rules with new ones in one go): |
|||
=== 動的 blackhole === |
|||
{{hc|atomic.rules|2= |
|||
table atomic { |
|||
このスニペットは、10/second の制限を超えた source IP (または /64 IPv6 range) からのすべての HTTPS 接続を 1 分間 drop します。 |
|||
chain incoming { |
|||
type filter hook input priority 0; |
|||
{{hc|/etc/nftables.conf| |
|||
ct state new reject |
|||
table inet dev { |
|||
} |
|||
set blackhole_ipv4 { |
|||
type ipv4_addr; |
|||
flags dynamic, timeout; |
|||
size 65536; |
|||
} |
|||
set blackhole_ipv6 { |
|||
type ipv6_addr; |
|||
flags dynamic, timeout; |
|||
size 65536; |
|||
} |
|||
chain input { |
|||
type filter hook input priority filter; policy accept; |
|||
ct state new meta l4proto { tcp, udp } th dport 443 \ |
|||
meter flood_ipv4 size 128000 { ip saddr timeout 10s limit rate over 10/second } \ |
|||
add @blackhole_ipv4 { ip saddr timeout 1m } |
|||
ct state new meta l4proto { tcp, udp } th dport 443 \ |
|||
meter flood_ipv6 size 128000 { ip6 saddr and ffff:ffff:ffff:ffff:: timeout 10s limit rate over 10/second } \ |
|||
add @blackhole_ipv6 { ip6 saddr and ffff:ffff:ffff:ffff:: timeout 1m } |
|||
ip saddr @blackhole_ipv4 counter drop |
|||
ip6 saddr and ffff:ffff:ffff:ffff:: @blackhole_ipv6 counter drop |
|||
} |
|||
} |
} |
||
}} |
|||
blackhole された IP を表示するには、{{ic|nft list set inet dev blackhole_ipv''X''}} を実行してください。 |
|||
table ip6 atomic { |
|||
chain incoming { |
|||
== ヒントとテクニック == |
|||
type filter hook input priority 0; |
|||
ct state new reject |
|||
=== 現在の rule set の保存 === |
|||
} |
|||
{{ic|nft list ruleset}} コマンドの出力は、そのまま有効な入力ファイルとしても使用できます。現在の rule set をファイルに保存し、後で読み戻すことができます。 |
|||
# nft -s list ruleset | tee ''filename'' |
|||
{{Note|元のファイルで変数定義を使っていた場合でも、{{ic|nft list}} は変数定義を出力しません。変数は失われます。ルール内で使われていた変数は、その値に置き換えられます。}} |
|||
=== シンプルなステートフルファイアウォール === |
|||
[[シンプルなステートフルファイアウォール]]の記事も参照してください。 |
|||
==== シングルマシン ==== |
|||
現在のルールセットを消去: |
|||
# nft flush ruleset |
|||
テーブルを追加: |
|||
# nft add table inet filter |
|||
input, forward, output ベースチェインを追加。input と forward のポリシーは破棄にして、output のポリシーは許可にする: |
|||
# nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; } |
|||
# nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; } |
|||
# nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; } |
|||
レギュラーチェインを追加して tcp と udp に関連付ける: |
|||
# nft add chain inet filter TCP |
|||
# nft add chain inet filter UDP |
|||
関連・確立済みトラフィックは許可する: |
|||
# nft add rule inet filter input ct state related,established accept |
|||
ループバックインターフェイスのトラフィックは全て許可する: |
|||
# nft add rule inet filter input iif lo accept |
|||
不正なトラフィックは全て破棄する: |
|||
# nft add rule inet filter input ct state invalid drop |
|||
新しいエコー要求 (ping) は許可する: |
|||
# nft add rule inet filter input ip protocol icmp icmp type echo-request ct state new accept |
|||
新しい udp トラフィックは UDP チェインにジャンプする: |
|||
# nft add rule inet filter input ip protocol udp ct state new jump UDP |
|||
新しい tcp トラフィックは TCP チェインにジャンプする: |
|||
# nft add rule inet filter input ip protocol tcp tcp flags \& \(fin\|syn\|rst\|ack\) == syn ct state new jump TCP |
|||
他のルールによって処理されなかったトラフィックは全て拒否する: |
|||
# nft add rule inet filter input ip protocol udp reject |
|||
# nft add rule inet filter input ip protocol tcp reject with tcp reset |
|||
# nft add rule inet filter input counter reject with icmp type prot-unreachable |
|||
ここから TCP と UDP チェインで処理する接続で開きたいポートを決めます。例えばウェブサーバーの接続を開くには: |
|||
# nft add rule inet filter TCP tcp dport 80 accept |
|||
ポート 443 からのウェブサーバーの HTTPS 接続を許可するには: |
|||
# nft add rule inet filter TCP tcp dport 443 accept |
|||
ポート 22 の SSH 接続を許可するには: |
|||
# nft add rule inet filter TCP tcp dport 22 accept |
|||
DNS リクエストを許可するには: |
|||
# nft add rule inet filter TCP tcp dport 53 accept |
|||
# nft add rule inet filter UDP tcp dport 53 accept |
|||
設定に満足したら変更を保存して永続化させてください。 |
|||
=== ブルートフォース攻撃の対策 === |
|||
[[Sshguard]] はブルートフォース攻撃を検出して一時的に IP アドレスに基づきブロックするようにファイアウォールを編集します。Sshguard で nftables を使うように設定する方法は [[Sshguard#nftables]] を見てください。 |
|||
=== トラフィックのログ記録 === |
|||
{{ic|log}} action を使ってパケットをログに記録できます。すべての受信 traffic をログに記録する最も単純なルールは次のとおりです: |
|||
# nft add rule inet filter input log |
|||
詳しくは [https://wiki.nftables.org/wiki-nftables/index.php/Logging_traffic nftables wiki] を参照してください。 |
|||
=== Monitor === |
|||
すべてのイベントを監視し、native nft format で報告します。 |
|||
# nft monitor |
|||
{{man|8|nft|MONITOR}} を参照してください。 |
|||
==== ruleset debugging trace temporary ==== |
|||
'''meta nftrace set 1''' は ruleset packet tracing を on/off します。trace を見るには [[#Monitor|monitor trace]] コマンドを使用します。 |
|||
別の shell で、interactive shell 内にファイルを "include" します: |
|||
# nft -i |
|||
nft> include "/root/nftables.trace" |
|||
必要に応じて調整した例です: |
|||
{{hc|/root/nftables.trace| |
|||
add table ip temp-trace {comment "Temporary table!!"; flags owner;} |
|||
add chain ip temp-trace icmp-prerouting { type filter hook prerouting priority raw - 1 ; } |
|||
add rule ip temp-trace icmp-prerouting ''ip protocol icmp'' '''meta nftrace set 1''' |
|||
}} |
|||
このファイルは一時テーブル (''flags owner'') を追加します。そのため、呼び出し元の interactive nft プロセスが閉じられると自動的に削除されます。Base Chain は用途に応じて調整する必要があります。複数のチェインや複数の "meta nftrace set 1" ルールを作成できます。"ip protocol icmp" は単なる例であり、必須ではありません。同様の効果を得る方法は多数あります。この方法の利点は、interactive shell を閉じることで以前の状態が自動的に復元されることと、ファイル内にエラーがある場合に何も実行されないことです。 |
|||
詳しくは [https://wiki.nftables.org/wiki-nftables/index.php/Ruleset_debug/tracing nftables wiki] と、その処理を自動化して色付けする [https://github.com/aborrero/nftables-tracer python tool] を参照してください。 |
|||
=== iptables-nft の使用 === |
|||
{{Accuracy|nftables は legacy iptables object が読み込まれている場合に警告するため、legacy iptables と nftables を同時に使うことが「完全に問題なく動作する」とは言えません。}} |
|||
古い iptables 言語は Linux ドキュメントでは依然としてかなり支配的であり、Docker のネットワークなど、iptables に依存して動作するものも少なくありません。legacy iptables と nftables を同時に使うことも可能ではありますが、iptables-nft の変換を使うことが推奨されます。理由は次のとおりです: |
|||
* すべてを新しく、より効率的で、ロックを必要としないフレームワークの同じ場所に配置します。 |
|||
* 競合をチェックします。 |
|||
nftables で古い iptables 言語を使用する方法は 2 つあります: |
|||
* {{ic|iptables-translate}} と {{ic|iptables-restore-translate}} ({{ic|ip6tables}}、{{ic|ebtables}} なども同様) は、iptables 言語を受け取り nft 言語を出力します。実行中の nft 設定は変更しません。{{man|8|xtables-translate}} を参照してください。 |
|||
: 後で保守したい設定については、{{ic|-translate}} ツールを使い、その結果のコードを既存のルールに統合するのがよいでしょう。例えば、[[シンプルなステートフルファイアウォール]]やインターネット上で便利なものを見つけた場合、それらを nft 設定に入れられるように変換できます。 |
|||
* {{ic|iptables}} と {{ic|iptables-restore}} ({{ic|ip6tables}} なども同様) は上記の変換を使い、さらに実行中の nft 設定に反映します。通常の iptables と同じように統計情報も提供します。{{man|8|xtables-nft}} を参照してください。 |
|||
: これらのコマンドは、やるべきことを考えれば十分にうまく動作します。単純な使い方では「そのまま動く」はずですが、ときどき手動でのデバッグが必要になることがあります。 |
|||
{{Note|translator は iptables 言語の大部分をカバーしていますが、すべてではありません。一部の iptables ルールは組み合わせて動作し、translator が正しく変換するには文脈が必要です。そのため、変換結果が空になる行があっても慌てないでください。}} |
|||
=== systemd-networkd を使った動的名前付きセット === |
|||
[[systemd-networkd]] の接続は、{{ic|NFTSet{{=}}}} オプションを使用して、事前定義された名前付きセットにホスト IP アドレス、ネットワークプレフィックス、インターフェイスインデックスを投入できます。これにより、{{ic|/etc/nftables.conf}} にそれらをハードコーディングすることを避けられます。{{ic|NFTSet{{=}}}} オプションは、{{ic|[Address]}}、{{ic|[DHCPv4]}}、{{ic|[DHCPv6]}}、{{ic|[IPv6AcceptRA]}} セクションでサポートされています。{{man|5|systemd.network|[ADDRESS] SECTION OPTIONS}} を参照してください。 |
|||
例えば、ローカルネットワークからの接続 (IP アドレスが DHCP または SLAAC で割り当てられる場合) を別の {{ic|my_input_lan}} チェインで処理するには: |
|||
{{hc|/etc/nftables.conf|2= |
|||
... |
|||
table inet my_table { |
|||
set eth_ipv4_prefix { |
|||
type ipv4_addr |
|||
flags interval |
|||
comment "Populated by systemd-networkd" |
|||
} |
|||
set eth_ipv6_prefix { |
|||
type ipv6_addr |
|||
flags interval |
|||
comment "Populated by systemd-networkd" |
|||
elements = { fe80::/10 } |
|||
} |
|||
set eth_ifindex { |
|||
type iface_index |
|||
comment "Populated by systemd-networkd" |
|||
} |
|||
... |
|||
chain my_input { |
|||
type filter hook input priority filter; policy drop; |
|||
iif @eth_ifindex ip6 saddr @eth_ipv6_prefix jump my_input_lan comment "Connections from LAN" |
|||
iif @eth_ifindex ip saddr @eth_ipv4_prefix jump my_input_lan comment "Connections from LAN" |
|||
} |
|||
... |
|||
} |
} |
||
}} |
}} |
||
Set the priority of other chains that hook input to higher than 0. This should block new connections while no other input chains are loaded. |
|||
{{hc|/etc/systemd/network/my-network.network|2= |
|||
===Rules Script with Atomic Fix=== |
|||
... |
|||
Because using {{ic|nft -f}} to reload rulesets is time consuming, it's far easier to script it. This will include an atomic fix not based on priorities. It uses the two rules files from above. |
|||
{{hc|firewall.sh|2= |
|||
#!/bin/sh |
|||
[DHCPv4] |
|||
# Load atomic rules first |
|||
NFTSet=prefix:inet:my_table:eth_ipv4_prefix |
|||
nft -f atomic.rules |
|||
NFTSet=ifindex:inet:my_table:eth_ifindex |
|||
[DHCPv6] |
|||
# New incoming traffic should now be stopped |
|||
NFTSet=prefix:inet:my_table:eth_ipv6_prefix |
|||
NFTSet=ifindex:inet:my_table:eth_ifindex |
|||
[IPv6AcceptRA] |
|||
# Get rid of both the ip and ip6 firewall tables |
|||
NFTSet=prefix:inet:my_table:eth_ipv6_prefix |
|||
NFTSet=ifindex:inet:my_table:eth_ifindex |
|||
... |
|||
}} |
|||
== トラブルシューティング == |
|||
nft flush table firewall 2>/dev/null |
|||
nft delete chain firewall incoming 2>/dev/null |
|||
nft delete table firewall 2>/dev/null |
|||
=== Docker と共に使う === |
|||
nft flush table ip6 firewall 2>/dev/null |
|||
nft delete chain ip6 firewall incoming 2>/dev/null |
|||
nft delete table ip6 firewall 2>/dev/null |
|||
{{Note| |
|||
# Reload the firewall rules |
|||
* 次のセットアップでは、{{ic|--net host --privileged}} を使用してもコンテナ内で {{ic|AF_BLUETOOTH}} などのプロトコルを利用できなくなります。 |
|||
nft -f firewall.rules |
|||
* ルートレス Dockerコンテナはすでに別のネットワーク名前空間で実行されています。何もする必要がないかもしれません。 |
|||
}} |
|||
nftables を使用すると、[[Docker]] のネットワーク (おそらく他のコンテナランタイムも同様) に干渉する可能性があります。 |
|||
# Get rid of both the ip and ip6 atomic tables |
|||
iptables ルールにパッチを適用して定義されたサービス開始順序を確保するか、docker の使用が非常に制限される dockerのiptablesの管理を完全に無効にするなど、さまざまな回避策がインターネット上で見つかります。 |
|||
(ポートフォワーディングや docker-compose を考えてください) |
|||
信頼できる方法は、docker を別のネットワーク名前空間で実行させ、そこで任意の処理を実行できるようにすることです。 |
|||
nft flush table atomic 2>/dev/null |
|||
Docker が nftables と iptables ルールを混在させないように、{{Pkg|iptables-nft}} を'''使用しない'''方が良いでしょう。 |
|||
nft delete chain atomic incoming 2>/dev/null |
|||
nft delete table atomic 2>/dev/null |
|||
以下の docker サービス [[ドロップインファイル]] を使用してください: |
|||
# New incoming IP traffic should be working |
|||
{{hc|/etc/systemd/system/docker.service.d/netns.conf|2= |
|||
nft flush table ip6 atomic 2>/dev/null |
|||
[Service] |
|||
nft delete chain ip6 atomic incoming 2>/dev/null |
|||
PrivateNetwork=yes |
|||
nft delete table ip6 atomic 2>/dev/null |
|||
PrivateMounts=No |
|||
# cleanup |
|||
# New incoming IPv6 traffic should be working |
|||
ExecStartPre=-nsenter -t 1 -n -- ip link delete docker0 |
|||
# add veth |
|||
ExecStartPre=nsenter -t 1 -n -- ip link add docker0 type veth peer name docker0_ns |
|||
ExecStartPre=sh -c 'nsenter -t 1 -n -- ip link set docker0_ns netns "$$BASHPID" && true' |
|||
ExecStartPre=ip link set docker0_ns name eth0 |
|||
# bring host online |
|||
ExecStartPre=nsenter -t 1 -n -- ip addr add 10.0.0.1/24 dev docker0 |
|||
ExecStartPre=nsenter -t 1 -n -- ip link set docker0 up |
|||
# bring ns online |
|||
ExecStartPre=ip addr add 10.0.0.100/24 dev eth0 |
|||
ExecStartPre=ip link set eth0 up |
|||
ExecStartPre=ip route add default via 10.0.0.1 dev eth0 |
|||
}} |
}} |
||
This should take anywhere from 100ms to 400ms, which is clearly unacceptable, but the only apparent solution. |
|||
セットアップにおいてIPアドレス {{ic|10.0.0.*}} が適切でない場合は、調整してください。 |
|||
==起動時にルールをロードする== |
|||
以下のポストルーティングルールで、{{ic|docker0}} のIPフォワーディングを有効にし、NATを設定します: |
|||
iifname docker0 oifname eth0 masquerade |
|||
システムの起動時にルールを自動的にロードするには、{{ic|systemctl enable nftables}} を実行して nftables の systemd サービスを有効にしてください。 |
|||
次に、[[インターネット共有#パケット転送の有効化|kernel IP forwarding]] が有効になっていることを確認します。 |
|||
{{Note|systemd サービスが正しく動作するように必要な nftables 関連のモジュール全てのエントリを含む {{ic|/etc/modules-load.d/nftables.conf}} を作成する必要があります。モジュールのリストは次のコマンドで取得可能です: {{bc|<nowiki>lsmod | grep nf</nowiki>}} 作成していないと、{{ic|Error: Could not process rule: No such file or directory}} エラーで終了してしまいます。}} |
|||
==Syslog にログを出力する== |
|||
これで、nftables を使用して {{ic|docker0}} インターフェイスのファイアウォールとポートフォワーディングを干渉することなくセットアップできるようになります。 |
|||
Syslog にログを残すには、{{ic|xt_LOG}} モジュールをロードする必要があります。 |
|||
==参照== |
==参照== |
||
* [ |
* [https://wiki.nftables.org/ netfilter nftables wiki] |
||
* [[debian:nftables]] |
|||
* [https://lwn.net/Articles/324251/ nftables の最初のリリース] |
|||
* [[gentoo:nftables]] |
|||
* [https://home.regit.org/netfilter-en/nftables-quick-howto/ nftables クイックハウツー] |
|||
* [https://lwn.net/Articles/ |
* [https://lwn.net/Articles/324251/ First release of nftables] |
||
* [https://home.regit.org/netfilter-en/nftables-quick-howto/ nftables quick howto] |
|||
* [https://lwn.net/Articles/564095/ The return of nftables] |
|||
* [https://developers.redhat.com/blog/2016/10/28/what-comes-after-iptables-its-successor-of-course/ What comes after ‘iptables’? Its successor, of course: `nftables`] |
|||
* [https://github.com/gene-git/blog/tree/master/nftables Gene's Tech Blog] – ワークステーションおよびファイアウォール向けの追加 nftables サンプル |
|||
2026年5月27日 (水) 13:16時点における最新版
nftables は既存の ip-, ip6-, arp-, ebtables フレームワークを置き換える Netfilter のプロジェクトです。新しいパケットフィルタリングフレームワーク、新しいユーザースペースユーティリティ (nft)、そして ip- と ip6tables の互換レイヤーを提供します。現行のフック、接続追跡システム、ユーザースペースのキューイングコンポーネント、そして netfilter のログサブシステムを使っています。
nftables は3つのメインコンポーネントから構成されています: カーネルの実装、libnl netlink communication そして nftables ユーザースペースフロントエンド。カーネルは netlink の設定インターフェイスだけでなく、小さなクラス言語インタプリタを使用するランタイムのルールセットの評価も提供します。libnl にはカーネルと通信するためのローレベルな関数が含まれています。nftables フロントエンドはユーザーが対話するものです。
nftables の公式 wiki には詳しい情報が載っています。
インストール
ユーザースペースユーティリティパッケージ nftables をインストールしてください。
iptables-legacy がインストールされている場合は、iptables をインストールしてください。これにより iptables-legacy が自動的にアンインストールされ、nftables との競合を防ぎます。
iptables コマンドの実装を提供します。ただし、古い iptables-legacy ツールで作成されたルールは別のオブジェクトであり、それらが存在する場合、iptables は警告を表示します。フロントエンド
- firewalld (firewall-cmd) — ネットワークとファイアウォールゾーンの設定、およびファイアウォールルールの設定と構成を行うデーモンおよびコンソールインターフェイス。
- nft-blackhole — 国別およびブラックリストによって nftables で IP をブロックするスクリプト / デーモン。
- ufw — Ufw は Uncomplicated Firewall の略で、netfilter ファイアウォールを管理するためのプログラムです。
- reaction — プログラムの出力から繰り返し出現するパターンをスキャンし、アクションを実行するデーモン。fail2ban の軽量な代替です。
使用方法
nftables は、コマンドラインで作成された一時的なルールと、ファイルから読み込まれた、またはファイルに保存された永続的なルールを区別しません。
すべてのルールは nft コマンドラインユーティリティを使って作成または読み込む必要があります。
使用方法については #設定 セクションを参照してください。
現在の ruleset は次のコマンドで表示できます:
# nft list ruleset
すべての ruleset を削除し、システムにファイアウォールがない状態にします:
# nft flush ruleset
nftables.service を再起動することで、/etc/nftables.conf から ruleset を読み込みます。
シンプルなファイアウォール
nftables には、/etc/nftables.conf ファイルに保存されたシンプルで安全なファイアウォール設定が付属しています。
nftables.service は、起動/有効化されたときに、そのファイルからルールを読み込みます。
設定
nftables ユーザースペースユーティリティ nft は、ruleset をカーネルに渡す前に、ルールセット評価の大部分を実行します。ルールはチェインに格納され、チェインはテーブルに格納されます。以下のセクションでは、これらの構造を作成および変更する方法を示します。
ファイルから入力を読み込むには、-f/--file オプションを使用します:
# nft --file filename
既に読み込まれているルールは自動的にはフラッシュされないことに注意してください。
すべてのコマンドの完全な一覧については nft(8) を参照してください。
テーブル
テーブルはチェインを保持します。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルの数や名前はユーザーが自由に決めることができますが、各テーブルにはアドレスファミリーをひとつしか保持することができません。5つのファミリーのうち指定したファミリーのパケットにだけ適用されます:
| nftables ファミリー | iptables ユーティリティ |
|---|---|
| ip | iptables |
| ip6 | ip6tables |
| inet | iptables と ip6tables |
| arp | arptables |
| bridge | ebtables |
ip (IPv4) がデフォルトのファミリーです。特に指定がなければ ip が使われます。
IPv4 と IPv6 の両方に適用されるルールを作成するには inet を使います。inet を使うには Linux 3.15 以上が必要で、ip と ip6 ファミリーを統一してルールを簡単に定義できます。
アドレスフファミリーの完全な定義は nft(8) の ADDRESS FAMILIES セクションを参照してください。
以下で例示しているコマンドの family は全て任意であり、指定しなかった場合は ip が使われます。
テーブルの作成
以下のコマンドで新しいテーブルが追加されます:
# nft add table family table
テーブルの一覧表示
全てのテーブルを表示するには:
# nft list tables
テーブル内のチェインとルールの表示
指定したテーブルの全てのチェインとルールを表示するには:
# nft list table family_type table_name
例えば、inet family の my_table テーブルのすべてのルールを一覧表示するには:
# nft list table inet my_table
テーブルの削除
テーブルを削除するには:
# nft delete table family_type table_name
これにより、テーブル内のすべてのチェインが破棄されます。
テーブルのクリア
テーブルから全てのルールを消去するには:
# nft flush table family_type table_name
チェイン
チェインの用途はルールを保持することです。iptables のチェインと違って、nftables には初めから組み込まれているチェインはありません。そのためチェインが netfilter フレームワークにあるタイプやフックをどれも使わない場合、iptables とは異なりチェインを通り抜けるパケットは nftables の影響を受けません。
チェインには2つのタイプがあります。base チェインはネットワークスタックからのパケットのエントリポイントとなります。フックの値を指定することができます。regular チェインはジャンプターゲットとして使用することができます。
以下のコマンドで使っている family_type は全て任意であり、指定しなかった場合は ip が使われます。
チェインの作成
Base chain
base chain を追加するには、type、hook、priority の値を指定する必要があります:
# nft add chain family_type table_name chain_name '{ type chain_type hook hook_type priority priority_value ; policy policy ;}'
chain_type には filter、route、nat を指定できます。
IPv4/IPv6/Inet address family では、hook_type に prerouting、input、forward、output、postrouting を指定できます。サポートされる family_type、chain_type、hook_type の組み合わせ一覧については nft(8) § CHAINS を参照してください。
priority_value には priority 名または整数値を指定できます。標準 priority 名と値の一覧については nft(8) § CHAINS を参照してください。数値が小さいチェインほど先に処理され、負の値も使用できます。[5]
任意で、base chain には policy (drop またはデフォルトの accept) を指定できます。これにより、チェイン内のルールで明示的に accept または refuse されなかったパケットに何が起こるかを定義します。
例えば、入力パケットをフィルタリングする base chain を追加するには:
# nft add chain inet my_table my_chain '{ type filter hook input priority 0; }'
上記のいずれでも add を create に置き換えると、新しいチェインを追加しますが、チェインが既に存在する場合はエラーを返します。
Regular chain
次のコマンドは、table_name という名前のテーブルに chain_name という名前の regular chain を追加します:
# nft add chain family_type table_name chain_name
例えば、inet address family の my_table テーブルに my_tcp_chain という regular chain を追加するには:
# nft add chain inet my_table my_tcp_chain
チェインの一覧表示
次のコマンドは、family_type のすべてのチェインを、ルールなしで一覧表示します (#ルールの一覧表示 を参照):
# nft list chains family_type
例えば、次のコマンドは IPv6 のチェインを一覧表示します:
# nft list chains ip6
family_type を省略した場合、すべてのチェインが表示されます。
チェインの編集
チェインを編集したいときは、チェインの名前を指定して変更したいルールを定義します:
# nft chain family_type table_name chain_name '{ [ type chain_type hook hook_type device device_name priority priority_value ; policy policy_type ; ] }'
例えば、デフォルトテーブル内の my_input チェインの policy を accept から drop に変更するには:
# nft chain inet my_table my_input '{ policy drop ; }'
チェインの削除
チェインを削除するには:
# nft delete chain family_type table_name chain_name
削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。
チェインのルールを消去
チェインからルールを消去するには:
# nft flush chain family_type table_name chain_name
ルール
ルールは表現または宣言から構成され、チェインの中に格納されます。
ルールの追加
チェインにルールを追加するには:
# nft add rule family_type table_name chain_name handle handle_value statement
ルールは handle_value の位置に追加されます。これは任意です。指定しない場合、ルールはチェインの末尾に追加されます。
ルール handle を確認するには、任意の有効な list コマンドに --handle スイッチを追加する必要があります。このスイッチにより、nft は出力に handle を表示します。--numeric 引数は、未解決の IP アドレスなど、一部の数値出力を確認するのに便利です。
# nft --handle --numeric list chain inet my_table my_input
table inet my_table {
chain input {
type filter hook input priority 0;
ip saddr 127.0.0.1 accept # handle 10
}
}
指定位置の前にルールを挿入するには:
# nft insert rule family_type table_name chain_name handle handle_value statement
handle_value が指定されていない場合、ルールはチェインの先頭に挿入されます。
表現
statement にはマッチする表現と判断宣言が入ります。判断宣言には accept, drop, queue, continue, return, jump chain, goto chain などが存在します。判断宣言以外の宣言も指定できます。詳しくは nft(8) を参照してください。
nftables では様々な表現を使うことができ、ほとんどは、iptables と対応するようになっています。一番大きな違いは汎用的なマッチと暗黙的なマッチが存在しないことです。汎用的なマッチとは、--protocol や --source のように、いつでも使うことができるマッチで、暗黙的なマッチとは、--sport のように、特定のプロトコルでしか使えないマッチのことです。
以下は利用できるマッチの一部です:
- meta (メタプロパティ。例: インターフェイス)
- icmp (ICMP プロトコル)
- icmpv6 (ICMPv6 プロトコル)
- ip (IP プロトコル)
- ip6 (IPv6 プロトコル)
- tcp (TCP プロトコル)
- udp (UDP プロトコル)
- sctp (SCTP プロトコル)
- ct (接続のトラッキング)
以下はマッチ引数の一部です (完全なリストは nft(8) を見て下さい):
meta: oif <output interface INDEX> iif <input interface INDEX> oifname <output interface NAME> iifname <input interface NAME> (oif and iif accept string arguments and are converted to interface indexes) (oifname and iifname are more dynamic, but slower because of string matching) icmp: type <icmp type> icmpv6: type <icmpv6 type> ip: protocol <protocol> daddr <destination address> saddr <source address> ip6: daddr <destination address> saddr <source address> tcp: dport <destination port> sport <source port> udp: dport <destination port> sport <source port> sctp: dport <destination port> sport <source port> ct: state <new | established | related | invalid>
ある意味では、iif と oif に対する iifname と oifname の違いは、static と dynamic の違いに似ています。または、プログラミング概念でいう definition と declaration、あるいは early binding と delayed binding に似ています。使用例と追加説明へのリンクについては [6] を参照してください。
ルールの一覧表示
次のコマンドはチェイン内のすべてのルールを一覧表示します:
# nft list chain family_type table_name chain_name
例えば、my_table という inet テーブル内の my_output というチェインのルールを一覧表示するには:
# nft list chain inet my_table my_output
削除
個々のルールはハンドルを使わないと削除することができません。nft --handle list コマンドを使うことでルールのハンドルを確認できます。例えば次のような場合:
# nft --handle --numeric list chain inet my_table my_input
table inet my_table {
chain input {
type filter hook input priority 0;
ip saddr 127.0.0.1 accept # handle 10
}
}
次のコマンドで削除できます:
# nft delete rule inet my_table my_input handle 10
テーブル内のすべてのチェインは nft flush table コマンドでフラッシュできます。個別のチェインは nft flush chain または nft delete rule コマンドでフラッシュできます。
# nft flush table table_name # nft flush chain family_type table_name chain_name # nft delete rule family_type table_name chain_name
最初のコマンドは、ip table_name テーブル内のすべてのチェインをフラッシュします。2 番目のコマンドは、family_type table_name テーブル内の chain_name チェインをフラッシュします。3 番目のコマンドは、family_type table_name テーブル内の chain_name チェインのすべてのルールを削除します。
セット
セットには名前付きセットと匿名セットがあります。セットは 1 つ以上の要素で構成され、要素はカンマで区切られ、波括弧で囲まれます。匿名セットはルールに埋め込まれ、更新できません。ルールを削除して再追加する必要があります。例えば、次の dports セットから "http" だけを削除することはできません:
# nft add rule ip6 filter input tcp dport {telnet, http, https} accept
名前付きセットは更新でき、型付けやフラグ付けが可能です。sshguard は、ブロックされたホストの IP アドレスに名前付きセットを使用します。
table ip sshguard {
set attackers {
type ipv4_addr
flags interval
elements = { 1.2.3.4 }
}
セットに要素を追加または削除するには、次のようにします:
# nft add element ip sshguard attackers { 5.6.7.8/32 }
# nft delete element ip sshguard attackers { 1.2.3.4/32 }
ipv4_addr 型には CIDR netmask を含められることに注意してください (ここでの /32 は必須ではありませんが、完全性のために含めています)。また、ここで TABLE ip sshguard { SET attackers } によって定義されたセットは、ip sshguard attackers として参照されることにも注意してください。
NFTSet= の説明と #systemd-networkd を使った動的名前付きセット の例を参照してください。アトミックリロード
現在のルールセットをフラッシュする:
# echo "flush ruleset" > /tmp/nftables
現在のルールセットをダンプする:
# nft list ruleset >> /tmp/nftables
/tmp/nftables を編集して次のコマンドで変更を適用:
# nft -f /tmp/nftables
サンプル
ワークステーション
/etc/nftables.conf
flush ruleset
table inet my_table {
set LANv4 {
type ipv4_addr
flags interval
elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
}
set LANv6 {
type ipv6_addr
flags interval
elements = { fd00::/8, fe80::/10 }
}
chain my_input_lan {
udp sport 1900 udp dport >= 1024 meta pkttype unicast limit rate 4/second burst 20 packets accept comment "Accept UPnP IGD port mapping reply"
udp sport netbios-ns udp dport >= 1024 meta pkttype unicast accept comment "Accept Samba Workgroup browsing replies"
}
chain my_input {
type filter hook input priority filter; policy drop;
iif lo accept comment "Accept any localhost traffic"
ct state invalid drop comment "Drop invalid connections"
fib daddr . iif type != { local, broadcast, multicast } drop comment "Drop packets if the destination IP address is not configured on the incoming interface (strong host model)"
ct state { established, related } accept comment "Accept traffic originated from us"
meta l4proto { icmp, ipv6-icmp } accept comment "Accept ICMP"
ip protocol igmp accept comment "Accept IGMP"
udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS"
udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS"
ip6 saddr @LANv6 jump my_input_lan comment "Connections from private IP address ranges"
ip saddr @LANv4 jump my_input_lan comment "Connections from private IP address ranges"
counter comment "Count any other traffic"
}
chain my_forward {
type filter hook forward priority filter; policy drop;
# Drop everything forwarded to us. We do not forward. That is routers job.
}
chain my_output {
type filter hook output priority filter; policy accept;
# Accept every outbound connection
}
}
NFTSet= を使って接続のネットワークプレフィックスを取得することで、ネットワークサブネットのハードコーディングを避けられます。#systemd-networkd を使った動的名前付きセット を参照してください。サーバー
/etc/nftables.conf
flush ruleset
table inet my_table {
set LANv4 {
type ipv4_addr
flags interval
elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
}
set LANv6 {
type ipv6_addr
flags interval
elements = { fd00::/8, fe80::/10 }
}
chain my_input_lan {
meta l4proto { tcp, udp } th dport 2049 accept comment "Accept NFS"
udp dport netbios-ns accept comment "Accept NetBIOS Name Service (nmbd)"
udp dport netbios-dgm accept comment "Accept NetBIOS Datagram Service (nmbd)"
tcp dport netbios-ssn accept comment "Accept NetBIOS Session Service (smbd)"
tcp dport microsoft-ds accept comment "Accept Microsoft Directory Service (smbd)"
udp sport { bootpc, 4011 } udp dport { bootps, 4011 } accept comment "Accept PXE"
udp dport tftp accept comment "Accept TFTP"
}
chain my_input {
type filter hook input priority filter; policy drop;
iif lo accept comment "Accept any localhost traffic"
ct state invalid drop comment "Drop invalid connections"
fib daddr . iif type != { local, broadcast, multicast } drop comment "Drop packets if the destination IP address is not configured on the incoming interface (strong host model)"
ct state { established, related } accept comment "Accept traffic originated from us"
meta l4proto { icmp, ipv6-icmp } accept comment "Accept ICMP"
ip protocol igmp accept comment "Accept IGMP"
udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS"
udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS"
ip6 saddr @LANv6 jump my_input_lan comment "Connections from private IP address ranges"
ip saddr @LANv4 jump my_input_lan comment "Connections from private IP address ranges"
tcp dport ssh accept comment "Accept SSH on port 22"
tcp dport ipp accept comment "Accept IPP/IPPS on port 631"
meta l4proto { tcp, udp } th dport { http, https, 8008, 8080 } accept comment "Accept HTTP (ports 80, 443, 8008, 8080)"
udp sport bootpc udp dport bootps ip saddr 0.0.0.0 ip daddr 255.255.255.255 accept comment "Accept DHCPDISCOVER (for DHCP-Proxy)"
}
chain my_forward {
type filter hook forward priority filter; policy drop;
# Drop everything forwarded to us. We do not forward. That is routers job.
}
chain my_output {
type filter hook output priority filter; policy accept;
# Accept every outbound connection
}
}
レート制限
table inet my_table {
chain my_input {
type filter hook input priority filter; policy drop;
iif lo accept comment "Accept any localhost traffic"
ct state invalid drop comment "Drop invalid connections"
fib daddr . iif type != { local, broadcast, multicast } drop comment "Drop packets if the destination IP address is not configured on the incoming interface (strong host model)"
meta l4proto icmp icmp type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods"
meta l4proto ipv6-icmp icmpv6 type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods"
ct state { established, related } accept comment "Accept traffic originated from us"
meta l4proto { icmp, ipv6-icmp } accept comment "Accept ICMP"
ip protocol igmp accept comment "Accept IGMP"
tcp dport ssh ct state new limit rate 15/minute accept comment "Avoid brute force on SSH"
}
}
ジャンプ
設定ファイルでジャンプを使うときは、先にターゲットチェインを定義する必要があります。そうしないと Error: Could not process rule: No such file or directory というエラーが発生します。
table inet my_table {
chain web {
tcp dport http accept
tcp dport 8080 accept
}
chain my_input {
type filter hook input priority filter;
ip saddr 10.0.2.0/24 jump web
drop
}
}
インターフェイスによってルールを変える
複数のネットワークインターフェイスが存在する場合、それぞれのインターフェイスごとに別々のフィルターチェインを設定したい場合があるかもしれません。例えば、ホームルーターを構築するとき、LAN 上でアクセスできるウェブサーバーを実行しつつ (nsp3s0 インターフェイス)、インターネットからはアクセスできないようにしたい場合 (enp2s0 インターフェイス) などは以下のように設定します:
table inet my_table {
chain my_input { # this chain serves as a dispatcher
type filter hook input priority filter; policy drop;
iif lo accept comment "always accept loopback"
iifname enp2s0 jump my_input_public
iifname enp3s0 jump my_input_private
}
chain my_input_public { # rules applicable to public interface interface
ct state {established,related} accept
ct state invalid drop
udp dport bootpc accept
tcp dport bootpc accept
}
chain my_input_private {
ct state {established,related} accept
ct state invalid drop
udp dport bootpc accept
tcp dport bootpc accept
tcp port http accept
tcp port https accept
reject with icmpx port-unreachable comment "all other traffic"
}
chain my_output { # we let everything out
type filter hook output priority filter;
accept
}
}
あるいは、単一の upstream interface に対する iifname statement だけを選び、それ以外のすべてのインターフェイスに対するデフォルトルールを 1 か所に置くこともできます。各インターフェイスごとに dispatch する必要はありません。
マスカレード
nftables には特殊なキーワード masquerade が存在し、送信元アドレスが自動的に出力インターフェイスのアドレスに設定されます (ソース)。ルーターのインターフェイスが多数の ISP に接続されているときなど、インターフェイスの IP アドレスが一定でない場合に有用です。通常は、インターフェイスの IP アドレスが変わるたびにネットワークアドレス変換 (NAT) のルールを更新する必要があります。
masquerade を使用するには:
- masquerading がカーネルで有効になっていることを確認してください (デフォルトカーネルを使用している場合は true です)。そうでない場合は、カーネル設定で
CONFIG_NFT_MASQ=mを設定します。 masqueradeキーワードはnattype のチェインでのみ使用できます。- masquerading は source NAT の一種であるため、output path でのみ動作します。
2 つのインターフェイスを持つマシンの例です: LAN は enp3s0 に接続され、public internet は enp2s0 に接続されています:
table inet my_nat {
chain my_masquerade {
type nat hook postrouting priority srcnat;
oifname "enp2s0" masquerade
}
}
テーブル type が inet なので、IPv4 と IPv6 の両方のパケットが masquerade されます。IPv6 は追加の address space により NAT が不要なため、IPv4 パケットだけを masquerade したい場合は、meta nfproto ipv4 expression を oifname "enp2s0" の前に使用するか、テーブル type を ip に変更します。
NAT とポートフォワーディング
この例では、eth0 という WAN インターフェイスを通って出ていくトラフィックを masquerade し、ポート 22 と 80 を 10.0.0.2 に転送します。sysctl によって net.ipv4.ip_forward を 1 に設定する必要があります。
table nat {
chain prerouting {
type nat hook prerouting priority dstnat;
iif eth0 tcp dport {22, 80} dnat to 10.0.0.2
}
chain postrouting {
type nat hook postrouting priority srcnat;
oif eth0 masquerade
}
}
IP ごとの新規接続数をカウント
HTTPS 接続をカウントするには、次のスニペットを使用します:
/etc/nftables.conf
table inet filter {
set https {
type ipv4_addr;
flags dynamic;
size 65536;
timeout 60m;
}
chain input {
type filter hook input priority filter;
ct state new meta l4proto { tcp, udp } th dport 443 update @https { ip saddr counter }
}
}
カウンターを表示するには、nft list set inet filter https を実行してください。
動的 blackhole
このスニペットは、10/second の制限を超えた source IP (または /64 IPv6 range) からのすべての HTTPS 接続を 1 分間 drop します。
/etc/nftables.conf
table inet dev {
set blackhole_ipv4 {
type ipv4_addr;
flags dynamic, timeout;
size 65536;
}
set blackhole_ipv6 {
type ipv6_addr;
flags dynamic, timeout;
size 65536;
}
chain input {
type filter hook input priority filter; policy accept;
ct state new meta l4proto { tcp, udp } th dport 443 \
meter flood_ipv4 size 128000 { ip saddr timeout 10s limit rate over 10/second } \
add @blackhole_ipv4 { ip saddr timeout 1m }
ct state new meta l4proto { tcp, udp } th dport 443 \
meter flood_ipv6 size 128000 { ip6 saddr and ffff:ffff:ffff:ffff:: timeout 10s limit rate over 10/second } \
add @blackhole_ipv6 { ip6 saddr and ffff:ffff:ffff:ffff:: timeout 1m }
ip saddr @blackhole_ipv4 counter drop
ip6 saddr and ffff:ffff:ffff:ffff:: @blackhole_ipv6 counter drop
}
}
blackhole された IP を表示するには、nft list set inet dev blackhole_ipvX を実行してください。
ヒントとテクニック
現在の rule set の保存
nft list ruleset コマンドの出力は、そのまま有効な入力ファイルとしても使用できます。現在の rule set をファイルに保存し、後で読み戻すことができます。
# nft -s list ruleset | tee filename
nft list は変数定義を出力しません。変数は失われます。ルール内で使われていた変数は、その値に置き換えられます。シンプルなステートフルファイアウォール
シンプルなステートフルファイアウォールの記事も参照してください。
シングルマシン
現在のルールセットを消去:
# nft flush ruleset
テーブルを追加:
# nft add table inet filter
input, forward, output ベースチェインを追加。input と forward のポリシーは破棄にして、output のポリシーは許可にする:
# nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
# nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }
# nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
レギュラーチェインを追加して tcp と udp に関連付ける:
# nft add chain inet filter TCP # nft add chain inet filter UDP
関連・確立済みトラフィックは許可する:
# nft add rule inet filter input ct state related,established accept
ループバックインターフェイスのトラフィックは全て許可する:
# nft add rule inet filter input iif lo accept
不正なトラフィックは全て破棄する:
# nft add rule inet filter input ct state invalid drop
新しいエコー要求 (ping) は許可する:
# nft add rule inet filter input ip protocol icmp icmp type echo-request ct state new accept
新しい udp トラフィックは UDP チェインにジャンプする:
# nft add rule inet filter input ip protocol udp ct state new jump UDP
新しい tcp トラフィックは TCP チェインにジャンプする:
# nft add rule inet filter input ip protocol tcp tcp flags \& \(fin\|syn\|rst\|ack\) == syn ct state new jump TCP
他のルールによって処理されなかったトラフィックは全て拒否する:
# nft add rule inet filter input ip protocol udp reject # nft add rule inet filter input ip protocol tcp reject with tcp reset # nft add rule inet filter input counter reject with icmp type prot-unreachable
ここから TCP と UDP チェインで処理する接続で開きたいポートを決めます。例えばウェブサーバーの接続を開くには:
# nft add rule inet filter TCP tcp dport 80 accept
ポート 443 からのウェブサーバーの HTTPS 接続を許可するには:
# nft add rule inet filter TCP tcp dport 443 accept
ポート 22 の SSH 接続を許可するには:
# nft add rule inet filter TCP tcp dport 22 accept
DNS リクエストを許可するには:
# nft add rule inet filter TCP tcp dport 53 accept # nft add rule inet filter UDP tcp dport 53 accept
設定に満足したら変更を保存して永続化させてください。
ブルートフォース攻撃の対策
Sshguard はブルートフォース攻撃を検出して一時的に IP アドレスに基づきブロックするようにファイアウォールを編集します。Sshguard で nftables を使うように設定する方法は Sshguard#nftables を見てください。
トラフィックのログ記録
log action を使ってパケットをログに記録できます。すべての受信 traffic をログに記録する最も単純なルールは次のとおりです:
# nft add rule inet filter input log
詳しくは nftables wiki を参照してください。
Monitor
すべてのイベントを監視し、native nft format で報告します。
# nft monitor
nft(8) § MONITOR を参照してください。
ruleset debugging trace temporary
meta nftrace set 1 は ruleset packet tracing を on/off します。trace を見るには monitor trace コマンドを使用します。
別の shell で、interactive shell 内にファイルを "include" します:
# nft -i nft> include "/root/nftables.trace"
必要に応じて調整した例です:
/root/nftables.trace
add table ip temp-trace {comment "Temporary table!!"; flags owner;}
add chain ip temp-trace icmp-prerouting { type filter hook prerouting priority raw - 1 ; }
add rule ip temp-trace icmp-prerouting ip protocol icmp meta nftrace set 1
このファイルは一時テーブル (flags owner) を追加します。そのため、呼び出し元の interactive nft プロセスが閉じられると自動的に削除されます。Base Chain は用途に応じて調整する必要があります。複数のチェインや複数の "meta nftrace set 1" ルールを作成できます。"ip protocol icmp" は単なる例であり、必須ではありません。同様の効果を得る方法は多数あります。この方法の利点は、interactive shell を閉じることで以前の状態が自動的に復元されることと、ファイル内にエラーがある場合に何も実行されないことです。
詳しくは nftables wiki と、その処理を自動化して色付けする python tool を参照してください。
iptables-nft の使用
古い iptables 言語は Linux ドキュメントでは依然としてかなり支配的であり、Docker のネットワークなど、iptables に依存して動作するものも少なくありません。legacy iptables と nftables を同時に使うことも可能ではありますが、iptables-nft の変換を使うことが推奨されます。理由は次のとおりです:
- すべてを新しく、より効率的で、ロックを必要としないフレームワークの同じ場所に配置します。
- 競合をチェックします。
nftables で古い iptables 言語を使用する方法は 2 つあります:
iptables-translateとiptables-restore-translate(ip6tables、ebtablesなども同様) は、iptables 言語を受け取り nft 言語を出力します。実行中の nft 設定は変更しません。xtables-translate(8) を参照してください。
- 後で保守したい設定については、
-translateツールを使い、その結果のコードを既存のルールに統合するのがよいでしょう。例えば、シンプルなステートフルファイアウォールやインターネット上で便利なものを見つけた場合、それらを nft 設定に入れられるように変換できます。
iptablesとiptables-restore(ip6tablesなども同様) は上記の変換を使い、さらに実行中の nft 設定に反映します。通常の iptables と同じように統計情報も提供します。xtables-nft(8) を参照してください。
- これらのコマンドは、やるべきことを考えれば十分にうまく動作します。単純な使い方では「そのまま動く」はずですが、ときどき手動でのデバッグが必要になることがあります。
systemd-networkd を使った動的名前付きセット
systemd-networkd の接続は、NFTSet= オプションを使用して、事前定義された名前付きセットにホスト IP アドレス、ネットワークプレフィックス、インターフェイスインデックスを投入できます。これにより、/etc/nftables.conf にそれらをハードコーディングすることを避けられます。NFTSet= オプションは、[Address]、[DHCPv4]、[DHCPv6]、[IPv6AcceptRA] セクションでサポートされています。systemd.network(5) § [ADDRESS SECTION OPTIONS] を参照してください。
例えば、ローカルネットワークからの接続 (IP アドレスが DHCP または SLAAC で割り当てられる場合) を別の my_input_lan チェインで処理するには:
/etc/nftables.conf
...
table inet my_table {
set eth_ipv4_prefix {
type ipv4_addr
flags interval
comment "Populated by systemd-networkd"
}
set eth_ipv6_prefix {
type ipv6_addr
flags interval
comment "Populated by systemd-networkd"
elements = { fe80::/10 }
}
set eth_ifindex {
type iface_index
comment "Populated by systemd-networkd"
}
...
chain my_input {
type filter hook input priority filter; policy drop;
iif @eth_ifindex ip6 saddr @eth_ipv6_prefix jump my_input_lan comment "Connections from LAN"
iif @eth_ifindex ip saddr @eth_ipv4_prefix jump my_input_lan comment "Connections from LAN"
}
...
}
/etc/systemd/network/my-network.network
... [DHCPv4] NFTSet=prefix:inet:my_table:eth_ipv4_prefix NFTSet=ifindex:inet:my_table:eth_ifindex [DHCPv6] NFTSet=prefix:inet:my_table:eth_ipv6_prefix NFTSet=ifindex:inet:my_table:eth_ifindex [IPv6AcceptRA] NFTSet=prefix:inet:my_table:eth_ipv6_prefix NFTSet=ifindex:inet:my_table:eth_ifindex ...
トラブルシューティング
Docker と共に使う
- 次のセットアップでは、
--net host --privilegedを使用してもコンテナ内でAF_BLUETOOTHなどのプロトコルを利用できなくなります。 - ルートレス Dockerコンテナはすでに別のネットワーク名前空間で実行されています。何もする必要がないかもしれません。
nftables を使用すると、Docker のネットワーク (おそらく他のコンテナランタイムも同様) に干渉する可能性があります。 iptables ルールにパッチを適用して定義されたサービス開始順序を確保するか、docker の使用が非常に制限される dockerのiptablesの管理を完全に無効にするなど、さまざまな回避策がインターネット上で見つかります。 (ポートフォワーディングや docker-compose を考えてください)
信頼できる方法は、docker を別のネットワーク名前空間で実行させ、そこで任意の処理を実行できるようにすることです。 Docker が nftables と iptables ルールを混在させないように、iptables-nft を使用しない方が良いでしょう。
以下の docker サービス ドロップインファイル を使用してください:
/etc/systemd/system/docker.service.d/netns.conf
[Service] PrivateNetwork=yes PrivateMounts=No # cleanup ExecStartPre=-nsenter -t 1 -n -- ip link delete docker0 # add veth ExecStartPre=nsenter -t 1 -n -- ip link add docker0 type veth peer name docker0_ns ExecStartPre=sh -c 'nsenter -t 1 -n -- ip link set docker0_ns netns "$$BASHPID" && true' ExecStartPre=ip link set docker0_ns name eth0 # bring host online ExecStartPre=nsenter -t 1 -n -- ip addr add 10.0.0.1/24 dev docker0 ExecStartPre=nsenter -t 1 -n -- ip link set docker0 up # bring ns online ExecStartPre=ip addr add 10.0.0.100/24 dev eth0 ExecStartPre=ip link set eth0 up ExecStartPre=ip route add default via 10.0.0.1 dev eth0
セットアップにおいてIPアドレス 10.0.0.* が適切でない場合は、調整してください。
以下のポストルーティングルールで、docker0 のIPフォワーディングを有効にし、NATを設定します:
iifname docker0 oifname eth0 masquerade
次に、kernel IP forwarding が有効になっていることを確認します。
これで、nftables を使用して docker0 インターフェイスのファイアウォールとポートフォワーディングを干渉することなくセットアップできるようになります。