コンテンツにスキップ

「Nftables」の版間の差分

提供: ArchWiki
削除された内容 追加された内容
参照: update
 
(11人の利用者による、間の25版が非表示)
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}}
[http://netfilter.org/projects/nftables/ nftables] は既存の ip-, ip6-, arp-, ebtables フレームワークを置き換える netfilter のプロジェクトです。新しいパケットフィルタリングフレームワーク、新しいユーザースペースユーティリティ (nft)、そして ip- と ip6tables の互換レイヤーを提供します。現行のフック、接続追跡システム、ユーザースペースのキューイングコンポーネント、そして netfilter のログサブシステムを使っています。
[https://netfilter.org/projects/nftables/ nftables] は既存の ip-, ip6-, arp-, ebtables フレームワークを置き換える [[Wikipedia:Netfilter|Netfilter]] のプロジェクトです。新しいパケットフィルタリングフレームワーク、新しいユーザースペースユーティリティ (nft)、そして ip- と ip6tables の互換レイヤーを提供します。現行のフック、接続追跡システム、ユーザースペースのキューイングコンポーネント、そして netfilter のログサブシステムを使っています。


nftables は3つのメインコンポーネントから構成されています: カーネルの実装、libnl netlink communication そして nftables ユーザースペースフロントエンド。カーネルは netlink の設定インターフェイスだけでなく、小さなクラス言語インタプリタを使用するランタイムのルールセットの評価も提供します。libnl にはカーネルと通信するためのローレベルな関数が含まれています。nftables フロントエンドはユーザーが対話するものです。
nftables は3つのメインコンポーネントから構成されています: カーネルの実装、libnl netlink communication そして nftables ユーザースペースフロントエンド。カーネルは netlink の設定インターフェイスだけでなく、小さなクラス言語インタプリタを使用するランタイムのルールセットの評価も提供します。libnl にはカーネルと通信するためのローレベルな関数が含まれています。nftables フロントエンドはユーザーが対話するものです。


[http://wiki.nftables.org nftables の公式 wiki] には詳しい情報が載っています。
[https://wiki.nftables.org/wiki-nftables/index.php/Main_Page nftables の公式 wiki] には詳しい情報が載っています。


== インストール ==
== インストール ==


ユーザースペースユーティリティパッケージ {{Pkg|nftables}} を[[インストール]]してください。
Linux カーネル 3.13 から nftables を使うことはできますが、できるかぎり最新のカーネルを使用すること推奨します。nftables のユーザーランドユーティリティは {{Pkg|nftables}} パッケージで利用できます。[[Arch User Repository|AUR]] には {{AUR|nftables-git}} パッケージも存在します。


{{Pkg|iptables-legacy}} がインストールされている場合は、{{Pkg|iptables}} をインストールしてください。これにより {{Pkg|iptables-legacy}} が自動的にアンインストールされ、{{Pkg|nftables}} との競合を防ぎます。
== 基本的な実装 ==


{{Note|{{Pkg|iptables}} パッケージは、実際には nftables ルールを作成し操作する {{ic|iptables}} コマンドの実装を提供します。ただし、古い {{Pkg|iptables-legacy}} ツールで作成されたルールは別のオブジェクトであり、それらが存在する場合、''iptables'' は警告を表示します。}}
他のファイアウォールと異なり、nftables ではコマンドラインで作成される一時的なルールと、ファイルに保存して読み込まれる永続的なルールを区別しています。デフォルトファイルの {{ic|/etc/nftables.conf}} には "inet filter" という名前のシンプルな ipv4/ipv6 ファイアウォールテーブルが既に記述されています。


=== ォルルールセットのロード ===
=== フロンエンド ===


{{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]}}
{{ic|nftables.service}} を[[起動]]・[[有効化]]してください。


* {{App|[[firewalld]] (firewall-cmd)|ネットワークとファイアウォールゾーンの設定、およびファイアウォールルールの設定と構成を行うデーモンおよびコンソールインターフェイス。|https://firewalld.org/|{{Pkg|firewalld}}}}
以下のコマンドでルールセットを確認できます:
* {{App|nft-blackhole|国別およびブラックリストによって nftables で IP をブロックするスクリプト / デーモン。|https://github.com/tomasz-c/nft-blackhole|{{AUR|nft-blackhole}}}}
* {{App|[[ufw]]|Ufw は Uncomplicated Firewall の略で、netfilter ファイアウォールを管理するためのプログラムです。|https://help.ubuntu.com/community/UFW|{{Pkg|ufw}}}}
* {{App|reaction|プログラムの出力から繰り返し出現するパターンをスキャンし、アクションを実行するデーモン。fail2ban の軽量な代替です。|https://framagit.org/ppom/reaction|{{AUR|reaction}}}}

== 使用方法 ==

{{Tip|すでに iptables ルールがある場合は、その iptables ルールを nftables ルールに変換できます。詳しくは [https://wiki.nftables.org/wiki-nftables/index.php/Moving_from_iptables_to_nftables] を参照してください。}}

'''nftables''' は、コマンドラインで作成された一時的なルールと、ファイルから読み込まれた、またはファイルに保存された永続的なルールを'''区別しません'''。

すべてのルールは {{ic|nft}} コマンドラインユーティリティを使って作成または読み込む必要があります。

使用方法については [[#設定]] セクションを参照してください。

現在の ruleset は次のコマンドで表示できます:


# nft list ruleset
# nft list ruleset


すべての ruleset を削除し、システムにファイアウォールがない状態にします:
inet filter テーブルの設定が表示された場合、デスクトップとしてインターネットを問題なく利用できます。


# nft flush ruleset
{{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}} エラーで終了してしまいます。}}


{{ic|nftables.service}} を[[再起動]]することで、{{ic|/etc/nftables.conf}} から ruleset を読み込みます。
== nft ==
nftables のユーザースペースユーティリティ {{ic|nft}} は現在カーネルのためにルールセットを処理する前にほとんどのルールセットの評価を行います。そのため、nftables はデフォルトのテーブルやチェインを提供していません。しかしながらユーザーが iptables のような設定をエミュレートすることが可能です。


=== シンプルなファイアウォール ===
{{Note|{{Pkg|nftables}} には "filter" テーブルが記述されている {{ic|/etc/nftables.conf}} が含まれています。このテーブルのルールでは、特定のプロトコルだけを許可して、他のプロトコルは全て拒否するようになっています。}}


{{Pkg|nftables}} には、{{ic|/etc/nftables.conf}} ファイルに保存されたシンプルで安全なファイアウォール設定が付属しています。
nft は 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}}) からなります。


{{ic|nftables.service}} は、[[起動/有効化]]されたときに、そのファイルからルールを読み込みます。
以下は nft で利用できるコマンドの不完全なリストです:

<nowiki>
== 設定 ==
list

tables [family]
nftables ユーザースペースユーティリティ {{ic|nft}} は、ruleset をカーネルに渡す前に、ルールセット評価の大部分を実行します。ルールはチェインに格納され、チェインはテーブルに格納されます。以下のセクションでは、これらの構造を作成および変更する方法を示します。
table [family] <name>
chain [family] <table> <name>


ファイルから入力を読み込むには、{{ic|-f}}/{{ic|--file}} オプションを使用します:
add
table [family] <name>
chain [family] <table> <name> [chain definitions]
rule [family] <table> <chain> <rule definition>


# nft --file ''filename''
table [family] <name> (shortcut for `add table`)


既に読み込まれているルールは'''自動的には'''フラッシュされないことに注意してください。
insert
rule [family] <table> <chain> <rule definition>


すべてのコマンドの完全な一覧については {{man|8|nft}} を参照してください。
delete
table [family] <name>
chain [family] <table> <name>
rule [family] <table> <handle>


===テーブル===
flush
table [family] <name>
chain [family] <table> <name></nowiki>
{{ic|family}} は任意ですが、デフォルトは {{ic|ip}} になります。


テーブルは[[#チェイン|チェイン]]を保持します。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルの数や名前はユーザーが自由に決めることができますが、各テーブルにはアドレスファミリーをひとつしか保持することができません。5つのファミリーのうち指定したファミリーのパケットにだけ適用されます:
==テーブル==
テーブルの用途はチェインを保持することです。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルは指定の5つのファミリーのうちどれか一つを持つことができ、それによって様々な iptables のユーティリティを一つに統一します:


{| class="wikitable"
{| class="wikitable"
84行目: 84行目:
| bridge || ebtables
| bridge || ebtables
|}
|}

=== ファミリー ===


{{ic|ip}} (IPv4) がデフォルトのファミリーです。特に指定がなければ {{ic|ip}} が使われます。
{{ic|ip}} (IPv4) がデフォルトのファミリーです。特に指定がなければ {{ic|ip}} が使われます。


IPv4 と IPv6 の両方に適用されるルールを作成するには {{ic|inet}} を使います。{{ic|inet}} を使うには Linux 3.15 以上が必要で、{{ic|ip}} と {{ic|ip6}} ファミリーを統一してルールを簡単に定義できます。
IPv6 は {{ic|ip6}} で指定できます。


{{Note|{{ic|inet}} は {{ic|nat}} タイプのチェインでは使えず、{{ic|filter}} タイプのチェインを使う必要があります ([https://www.spinics.net/lists/netfilter/msg56411.html ソース])。}}
IPv4 と IPv6 の両方に適用されるルールを作成するには {{ic|inet}} を使います。Linux 3.15 以上が必要で、{{ic|ip}} と {{ic|ip6}} ファミリーを統一してルールを簡単に定義できます。


アドレスフファミリーの完全な定義は {{man|8|nft}} の {{ic|ADDRESS FAMILIES}} セクションを参照してください。
{{Note|{{ic|inet}} は {{ic|nat}} タイプのチェインでは使えず、{{ic|filter}} タイプのチェインを使う必要があります ([http://www.spinics.net/lists/netfilter/msg56411.html ソース])。}}

以下で例示しているコマンドの {{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)


これにより、テーブル内のすべてのチェインが破棄されます。
=====フック=====
チェインは6つのフックを使うことができ、ingress 以外は iptables で使われているチェインと対応しています:
*ingress
*input
*output
*forward
*prerouting
*postrouting


==== テーブルのクリア ====
ingress フックは既存の {{ic|tc}} ユーティリティを置き換えます。


テーブルから全てのルールを消去するには:
=====プライオリティ=====
{{Note|
* パケットが先に来るチェインにはプライオリティの効果はありません。
* プライオリティは符号なしの整数として設定するようになっているため、負のプライオリティを設定した場合、優先度は逆に高くなります。}}
プライオリティは nftables がどのパケットを初めに通過させるかを示します。整数で指定し、高い値を与えるほど優先されます。


# nft flush table ''family_type'' ''table_name''
=== 編集 ===


===チェイン===
チェインを編集するには、以下のようにコマンドを実行してください:


チェインの用途は[[#ルール|ルール]]を保持することです。iptables のチェインと違って、nftables には初めから組み込まれているチェインはありません。そのためチェインが netfilter フレームワークにあるタイプやフックをどれも使わない場合、iptables とは異なりチェインを通り抜けるパケットは nftables の影響を受けません。
# <nowiki>nft chain <table> <family> <chain> { [ type <type> hook <hook> device <device> priority <priority> \; policy <policy> \; ] }</nowiki>


チェインには2つのタイプがあります。''base'' チェインはネットワークスタックからのパケットのエントリポイントとなります。フックの値を指定することができます。''regular'' チェインはジャンプターゲットとして使用することができます。
例えば、デフォルトテーブルの input チェインのポリシーを "accept" から "drop" に変更するには:


以下のコマンドで使っている {{ic|''family_type''}} は全て任意であり、指定しなかった場合は {{ic|ip}} が使われます。
# nft chain inet filter input { policy drop \; }


==== チェインの作成 ====
===削除===
チェインはルールが存在しない場合にのみ削除することができます。
# nft delete chain ''foo bar''
# nft delete chain ''ip6 foo bar''
以上のコマンドは ip と ip6 の {{ic|foo}} テーブルから {{ic|bar}} チェインを削除します。


===== Base chain =====
==ルール==
ルールの用途はパケットを識別(マッチ)して処理を実行(ジャンプ)することです。iptables と同じように、様々なマッチやジャンプが利用できますが、nftables には欠けている機能も存在します。


base chain を追加するには、type、hook、priority の値を指定する必要があります:
===表示===
テーブルを表示するのと同じ方法を使って、{{ic|nft list}} コマンドでテーブルの中の現在のルールを表示することができます。個別のチェインからルールを表示することも可能です。
# nft list chain ''foo bar''
# nft list chain ''ip6 foo bar''
上記のコマンドで、ip と ip6 の {{ic|foo}} テーブルの {{ic|bar}} チェインのルールが表示されます。


# nft add chain ''family_type'' ''table_name'' ''chain_name'' '{ type ''chain_type'' hook ''hook_type'' priority ''priority_value'' ; policy ''policy'' ;}'
===作成===
テーブルがファイル定義や {{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
上記のコマンドで、ip と ip6 の {{ic|foo}} テーブルの {{ic|bar}} チェインにルールが追加され、{{ic|saddr}} (ソースアドレス) が 127.0.0.1 (IPv4) や ::1 (IPv6) の場合に {{ic|ip}} パケットにマッチして、パケットを許可します。


{{ic|''chain_type''}} には {{ic|filter}}、{{ic|route}}、{{ic|nat}} を指定できます。
====マッチ====

nftables では様々なマッチを使うことができ、ほとんどは、iptables と対応するようになっています。一番大きな違いは汎用的なマッチと暗黙的なマッチが存在しないことです。汎用的なマッチとは、{{ic|--protocol}} や {{ic|--source}} のように、いつでも使うことができるマッチで、暗黙的なマッチとは、{{ic|--sport}} のように、特定のプロトコルでしか使えないマッチのことです。
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}} のように、特定のプロトコルでしか使えないマッチのことです。


以下は利用できるマッチの一部です:
以下は利用できるマッチの一部です:
204行目: 256行目:
* ct (接続のトラッキング)
* ct (接続のトラッキング)


以下はマッチ引数の一部です (完全なリストは {{man|8|nft|url=http://www.netfilter.org/projects/nftables/manpage.html}} を見て下さい):
以下はマッチ引数の一部です (完全なリストは {{man|8|nft}} を見て下さい):
<nowiki>
<nowiki>
meta:
meta:
245行目: 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 (パケットを許可)
*reject (パケットを拒否)
*drop (パケットを破棄)
*snat (送信元 NAT を実行)
*dnat (宛先 NAT を実行)
*log (パケットを記録)
*counter (パケットカウンタを保持、nftables ではカウンタはオプションです)
*return (チェインの横断を停止)
*jump <chain> (他のチェインにジャンプ)
*goto <chain> (他のチェインにジャンプ、元のチェインに戻らない)


次のコマンドはチェイン内のすべてのルールを一覧表示します:
===挿入===


# nft list chain ''family_type'' ''table_name'' ''chain_name''
====先頭に追加====
{{ic|nft insert rule}} コマンドでチェインにルールを挿入することができます。
# nft insert rule filter input ct state established,related accept


例えば、{{ic|my_table}} という {{ic|inet}} テーブル内の {{ic|my_output}} というチェインのルールを一覧表示するには:
==== 特定の場所に追加 ====


# nft list chain inet my_table my_output
Nftables はハンドルを使用してルールの位置を定義します。情報を取得するには、-a フラグを付けてルールセットを確認してください:


====削除====
# nft list ruleset -a


個々のルールはハンドルを使わないと削除することができません。{{ic|nft --handle list}} コマンドを使うことでルールのハンドルを確認できます。例えば次のような場合:
特定のハンドラが付いているルールの後にルールを追加するには:


{{hc|# nft --handle --numeric list chain inet my_table my_input|2=<nowiki>
# nft add rule ''table_name'' ''chain_name'' position ''handler_number'' ''[rule-definition]''
table inet my_table {

===削除===
個々のルールはハンドルを使わないと削除することができません。{{ic|nft --handle list}} コマンドを使うことでルールのハンドルを確認できます。{{ic|--handle}} スイッチを付けると、{{ic|nft}} はハンドルを出力するようになります。

以下ではルールのハンドルを確認してルールを削除しています。未解決の IP アドレスのような、数字の出力を表示するときは {{ic|--number}} 引数を使うと良いでしょう。
{{hc|# nft --handle --numeric list chain filter input|2=
<nowiki>
table ip fltrTable {
chain input {
chain input {
type filter hook input priority 0;
type filter hook input priority 0;
289行目: 320行目:
}
}
}
}
</nowiki>
</nowiki>}}
}}
# nft delete rule fltrTable input handle 10


次のコマンドで削除できます:
{{ic|nft flush table}} コマンドを使うことでテーブルの全てのチェインをフラッシュできます。個別のチェインをフラッシュするときは {{ic|nft flush chain}} または {{ic|nft delete rule}} コマンドを使います。

# 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
最初のコマンドでは ip {{ic|foo}} テーブルのチェイン全てをフラッシュします。2番目のコマンド ip {{ic|foo}} テーブルの {{ic|bar}} チェイフラッシュます。3番目コマ ip6 {{ic|foo}} テーブルの {{ic|bar}} チェイの全てのルールを削除します。
テーブル内のすべてのチェインは {{ic|nft flush table}} コマドでフラッシュできます。個別チェインは {{ic|nft flush chain}} または {{ic|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 {{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
# echo "flush ruleset" > /tmp/nftables

現在のルールセットをダンプする:
現在のルールセットをダンプする:

# nft list ruleset >> /tmp/nftables
# nft list ruleset >> /tmp/nftables

{{ic|/tmp/nftables}} を編集して次のコマンドで変更を適用:
{{ic|/tmp/nftables}} を編集して次のコマンドで変更を適用:

# nft -f /tmp/nftables
# nft -f /tmp/nftables


==ファイ定義==
== サンプ ==
{{ic|nft -f}} コマンドでファイル定義を利用することができます。このコマンドは {{ic|iptables-restore}} コマンドと同じように動作します。ただし、{{ic|iptables-restore}} と違って、既存のルールセットをフラッシュしないので、前もって flush コマンドを実行する必要があります。
{{hc|/etc/nftables/filter.rules|2=
<nowiki>
flush table ip filter
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>
}}


=== ワークステーション ===
ルールを ({{ic|iptables-save}} のように) エクスポートするには:
# nft list ruleset


{{hc|/etc/nftables.conf|2=<nowiki>
==基本的なファイアウォール==
flush ruleset
以下の例は ''nft'' コマンドを使ってベーシックな ''IPv4'' ファイアウォールを設定する方法を示しています。IPv4 と IPv6 の両方をフィルタリングしたい場合、{{ic|/usr/share/nftables}} にある他のサンプルを見たり、{{ic|/etc/nftables.conf}} のデフォルト (IPv4/IPv6 で動作するように設定済みです) を使うようにしてください。


table inet my_table {
[[iptables]] のようなチェインを設定するには、まず備え付けの IPv4 フィルターファイルを使う必要があります:
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 }
# nft -f /usr/share/nftables/ipv4-filter
}
set LANv6 {
type ipv6_addr
flags interval


elements = { fd00::/8, fe80::/10 }
作成されたチェインを表示するには:
}


chain my_input_lan {
# nft list table filter
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"
特定の宛先への出力を破棄:


}
# nft add rule ip filter output ip daddr 1.2.3.4 drop


chain my_input {
宛先がローカルのポート 80 のパケットを破棄:
type filter hook input priority filter; policy drop;


iif lo accept comment "Accept any localhost traffic"
# nft add rule ip filter input tcp dport 80 drop
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"
# nft delete rule filter output
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"
===シンプルな IP/IPv6 ファイアウォール===


counter comment "Count any other traffic"
{{hc|firewall.rules|2=<nowiki>
}
# A simple firewall


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
}

}
</nowiki>}}

{{Tip|[[systemd-networkd]] を使用していてローカルネットワークに接続している場合、{{man|5|systemd.network}} オプション {{ic|NFTSet{{=}}}} を使って接続のネットワークプレフィックスを取得することで、ネットワークサブネットのハードコーディングを避けられます。[[#systemd-networkd を使った動的名前付きセット]] を参照してください。}}

=== サーバー ===

{{hc|/etc/nftables.conf|2=<nowiki>
flush ruleset
flush ruleset


table inet filter {
table inet my_table {
chain input {
set LANv4 {
type ipv4_addr
type filter hook input priority 0; policy drop;
flags interval


elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
# established/related connections
}
ct state established,related accept
set LANv6 {
type ipv6_addr
flags interval


elements = { fd00::/8, fe80::/10 }
# invalid connections
}
ct state invalid drop
# loopback interface
iif lo accept


chain my_input_lan {
# ICMP
meta l4proto { tcp, udp } th dport 2049 accept comment "Accept NFS"
# routers may also want: mld-listener-query, nd-router-solicit
ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
ip protocol icmp icmp type { destination-unreachable, router-advertisement, time-exceeded, parameter-problem } accept


udp dport netbios-ns accept comment "Accept NetBIOS Name Service (nmbd)"
# SSH (port 22)
tcp dport ssh accept
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"
# HTTP (ports 80 & 445)
tcp dport { http, https } accept
udp dport tftp accept comment "Accept TFTP"
}
}
}</nowiki>}}


chain my_input {
===Limit rate IP/IPv6 ファイアウォール===
type filter hook input priority filter; policy drop;


iif lo accept comment "Accept any localhost traffic"
{{hc|firewall.2.rules|2=<nowiki>
ct state invalid drop comment "Drop invalid connections"
table inet filter {
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)"
chain input {
ct state { established, related } accept comment "Accept traffic originated from us"
type filter hook input priority 0; policy drop;


meta l4proto { icmp, ipv6-icmp } accept comment "Accept ICMP"
# no ping floods:
ip protocol igmp accept comment "Accept IGMP"
ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 10/second accept
ip protocol icmp icmp type echo-request limit rate 10/second accept


udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS"
ct state established,related accept
udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS"
ct state invalid drop


ip6 saddr @LANv6 jump my_input_lan comment "Connections from private IP address ranges"
iifname lo accept
ip saddr @LANv4 jump my_input_lan comment "Connections from private IP address ranges"


tcp dport ssh accept comment "Accept SSH on port 22"
# avoid brute force on ssh:
tcp dport ssh limit rate 15/minute accept


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
}

}
</nowiki>}}

=== レート制限 ===

{{bc|1=<nowiki>
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"

}

}
}
</nowiki>}}
</nowiki>}}


===ジャンプ===
===ジャンプ===

設定ファイルでジャンプを使うときは、先にターゲットチェインを定義する必要があります。そうしないと {{ic|Error: Could not process rule: No such file or directory}} というエラーが発生します。
設定ファイルでジャンプを使うときは、先にターゲットチェインを定義する必要があります。そうしないと {{ic|Error: Could not process rule: No such file or directory}} というエラーが発生します。

{{hc|jump.rules|2=
<nowiki>
{{bc|1=<nowiki>
table inet filter {
table inet my_table {
chain web {
chain web {
tcp dport http accept
tcp dport http accept
tcp dport 8080 accept
tcp dport 8080 accept
}
}
chain input {
chain my_input {
type filter hook input priority 0;
type filter hook input priority filter;
ip saddr 10.0.2.0/24 jump web
ip saddr 10.0.2.0/24 jump web
drop
drop
}
}
}
}
</nowiki>
</nowiki>}}
}}

== 実践的なサンプル ==


=== インターフェイスによってルールを変える ===
=== インターフェイスによってルールを変える ===
431行目: 553行目:
複数のネットワークインターフェイスが存在する場合、それぞれのインターフェイスごとに別々のフィルターチェインを設定したい場合があるかもしれません。例えば、ホームルーターを構築するとき、LAN 上でアクセスできるウェブサーバーを実行しつつ ({{ic|nsp3s0}} インターフェイス)、インターネットからはアクセスできないようにしたい場合 ({{ic|enp2s0}} インターフェイス) などは以下のように設定します:
複数のネットワークインターフェイスが存在する場合、それぞれのインターフェイスごとに別々のフィルターチェインを設定したい場合があるかもしれません。例えば、ホームルーターを構築するとき、LAN 上でアクセスできるウェブサーバーを実行しつつ ({{ic|nsp3s0}} インターフェイス)、インターネットからはアクセスできないようにしたい場合 ({{ic|enp2s0}} インターフェイス) などは以下のように設定します:


<nowiki>table inet filter {
{{bc|<nowiki>
table inet my_table {
chain input { # this chain serves as a dispatcher
chain my_input { # this chain serves as a dispatcher
type filter hook input priority 0;
type filter hook input priority filter; policy drop;

iifname lo accept # always accept loopback
iifname enp2s0 jump input_enp2s0
iifname enp3s0 jump input_enp3s0


iif lo accept comment "always accept loopback"
reject with icmp type port-unreachable # refuse traffic from all other interfaces
iifname enp2s0 jump my_input_public
iifname enp3s0 jump my_input_private
}
}
chain input_enp2s0 { # rules applicable to public interface interface
chain my_input_public { # rules applicable to public interface interface
ct state {established,related} accept
ct state {established,related} accept
ct state invalid drop
ct state invalid drop
udp dport bootpc accept
udp dport bootpc accept
tcp dport bootpc accept
tcp dport bootpc accept
reject with icmp type port-unreachable # all other traffic
}
}
chain input_enp3s0 {
chain my_input_private {
ct state {established,related} accept
ct state {established,related} accept
ct state invalid drop
ct state invalid drop
455行目: 575行目:
tcp port http accept
tcp port http accept
tcp port https accept
tcp port https accept
reject with icmp type port-unreachable # all other traffic
reject with icmpx port-unreachable comment "all other traffic"
}
}
chain ouput { # we let everything out
chain my_output { # we let everything out
type filter hook output priority 0;
type filter hook output priority filter;
accept
accept
}
}
}
}</nowiki>
</nowiki>}}


もしくは {{ic|iifname}} ステートメント特定インターフェイスで使用し、他のインターフェイスについてはデフォルトルールを設定するいう方法もありま
あるい、単一の upstream interface に対する {{ic|iifname}} statement だけ選び、それ以外すべてのインターフェイスに対するデフォルトルールを 1 か所に置くこともできます。各インターフェイスごとに dispatch する必要はありません


=== マスカレード ===
=== マスカレード ===
471行目: 592行目:
{{ic|masquerade}} を使用するには:
{{ic|masquerade}} を使用するには:


* カーネルのバージョンが 3.18 以上である必要があります。
* カーネルコンフィグで以下のマスカレード設定が有効になっている必要があります。


* masquerading がカーネルで有効になっていることを確認してください (デフォルトカーネルを使用している場合は true です)。そうでない場合は、カーネル設定で {{ic|1=CONFIG_NFT_MASQ=m}} を設定します。
CONFIG_NFT_MASQ=m
* {{ic|masquerade}} キーワードは {{ic|nat}} type のチェインでのみ使用できます。
* masquerading は source NAT の一種であるため、output path でのみ動作します。


2 つのインターフェイスを持つマシンの例です: LAN は {{ic|enp3s0}} に接続され、public internet は {{ic|enp2s0}} に接続されています:
* {{ic|masquerade}} キーワードは {{ic|nat}} タイプのチェインでのみ使うことができ、{{ic|inet}} ファミリーのテーブルでは利用できません。{{ic|ip}} ファミリーや {{ic|ip6}} ファミリーのテーブルを使ってください。
* マスカレードは一種のソース NAT であり、出力パスでのみ機能します。


{{bc|<nowiki>
2つのインターフェイスが存在し {{ic|nsp3s0}} が LAN に接続され、{{ic|enp2s0}} がインターネットに接続されているマシンでの設定例:
table inet my_nat {

chain my_masquerade {
<nowiki>table ip nat {
type nat hook postrouting priority srcnat;
chain prerouting {
oifname "enp2s0" masquerade
type nat hook prerouting priority 0;
}
}
}
chain postrouting {
</nowiki>}}
type nat hook postrouting priority 0;

oifname "enp0s2" masquerade
テーブル type が {{ic|inet}} なので、IPv4 と IPv6 の両方のパケットが masquerade されます。IPv6 は追加の address space により NAT が不要なため、IPv4 パケットだけを masquerade したい場合は、{{ic|meta nfproto ipv4}} expression を {{ic|oifname "enp2s0"}} の前に使用するか、テーブル type を {{ic|ip}} に変更します。
}

}</nowiki>
=== NAT とポートフォワーディング ===

この例では、eth0 という WAN インターフェイスを通って出ていくトラフィックを masquerade し、ポート 22 と 80 を {{ic|10.0.0.2}} に転送します。[[sysctl]] によって {{ic|net.ipv4.ip_forward}} を {{ic|1}} に設定する必要があります。

{{bc|
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 接続をカウントするには、次のスニペットを使用します:

{{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 }
}
}
}}

カウンターを表示するには、{{ic|nft list set inet filter https}} を実行してください。

=== 動的 blackhole ===

このスニペットは、10/second の制限を超えた source IP (または /64 IPv6 range) からのすべての HTTPS 接続を 1 分間 drop します。

{{hc|/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 を表示するには、{{ic|nft list set inet dev blackhole_ipv''X''}} を実行してください。

== ヒントとテクニック ==

=== 現在の 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"
}
...
}
}}

{{hc|/etc/systemd/network/my-network.network|2=
...

[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 と共に使う ===

{{Note|
* 次のセットアップでは、{{ic|--net host --privileged}} を使用してもコンテナ内で {{ic|AF_BLUETOOTH}} などのプロトコルを利用できなくなります。
* ルートレス Dockerコンテナはすでに別のネットワーク名前空間で実行されています。何もする必要がないかもしれません。
}}

nftables を使用すると、[[Docker]] のネットワーク (おそらく他のコンテナランタイムも同様) に干渉する可能性があります。
iptables ルールにパッチを適用して定義されたサービス開始順序を確保するか、docker の使用が非常に制限される dockerのiptablesの管理を完全に無効にするなど、さまざまな回避策がインターネット上で見つかります。
(ポートフォワーディングや docker-compose を考えてください)

信頼できる方法は、docker を別のネットワーク名前空間で実行させ、そこで任意の処理を実行できるようにすることです。
Docker が nftables と iptables ルールを混在させないように、{{Pkg|iptables-nft}} を'''使用しない'''方が良いでしょう。

以下の docker サービス [[ドロップインファイル]] を使用してください:

{{hc|/etc/systemd/system/docker.service.d/netns.conf|2=
[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アドレス {{ic|10.0.0.*}} が適切でない場合は、調整してください。

以下のポストルーティングルールで、{{ic|docker0}} のIPフォワーディングを有効にし、NATを設定します:

iifname docker0 oifname eth0 masquerade

次に、[[インターネット共有#パケット転送の有効化|kernel IP forwarding]] が有効になっていることを確認します。


==Syslog にログを出力する==


これで、nftables を使用して {{ic|docker0}} インターフェイスのファイアウォールとポートフォワーディングを干渉することなくセットアップできるようになります。
Linux カーネル 3.17 未満を使っている場合、ログ出力を有効にするには {{ic|xt_LOG}} を modprobe する必要があります。


==参照==
==参照==
* [https://wiki.nftables.org/ netfilter nftables wiki]
* [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/564095/ nftables の帰還]
* [https://lwn.net/Articles/324251/ First release of nftables]
* [https://home.regit.org/netfilter-en/nftables-quick-howto/ nftables quick howto]
* [http://developers.redhat.com/blog/2016/10/28/what-comes-after-iptables-its-successor-of-course-nftables/ What comes after ‘iptables’? It’s successor, of course: `nftables`]
* [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 パッケージは、実際には nftables ルールを作成し操作する iptables コマンドの実装を提供します。ただし、古い iptables-legacy ツールで作成されたルールは別のオブジェクトであり、それらが存在する場合、iptables は警告を表示します。

フロントエンド

ヒント ほとんどの iptables フロントエンドは nftables を直接または間接的にサポートしていませんが、将来的に対応する可能性があります。[1] nftables と iptables の両方をサポートするグラフィカルフロントエンドの 1 つは firewalld です。[2] ufw は互換レイヤー iptables-nft を介してサポートされています。[3]
  • firewalld (firewall-cmd) — ネットワークとファイアウォールゾーンの設定、およびファイアウォールルールの設定と構成を行うデーモンおよびコンソールインターフェイス。
https://firewalld.org/ || firewalld
  • nft-blackhole — 国別およびブラックリストによって nftables で IP をブロックするスクリプト / デーモン。
https://github.com/tomasz-c/nft-blackhole || nft-blackholeAUR
  • ufw — Ufw は Uncomplicated Firewall の略で、netfilter ファイアウォールを管理するためのプログラムです。
https://help.ubuntu.com/community/UFW || ufw
  • reaction — プログラムの出力から繰り返し出現するパターンをスキャンし、アクションを実行するデーモン。fail2ban の軽量な代替です。
https://framagit.org/ppom/reaction || reactionAUR

使用方法

ヒント すでに iptables ルールがある場合は、その iptables ルールを nftables ルールに変換できます。詳しくは [4] を参照してください。

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 以上が必要で、ipip6 ファミリーを統一してルールを簡単に定義できます。

ノート inetnat タイプのチェインでは使えず、filter タイプのチェインを使う必要があります (ソース)。

アドレスフファミリーの完全な定義は 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 には filterroutenat を指定できます。

IPv4/IPv6/Inet address family では、hook_typepreroutinginputforwardoutputpostrouting を指定できます。サポートされる family_typechain_typehook_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; }'

上記のいずれでも addcreate に置き換えると、新しいチェインを追加しますが、チェインが既に存在する場合はエラーを返します。

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

ルール

ルールは表現または宣言から構成され、チェインの中に格納されます。

ルールの追加

ヒント iptables-translate ユーティリティを使うことで iptables のルールを nftables フォーマットに変換できます。

チェインにルールを追加するには:

# 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 として参照されることにも注意してください。

ヒント systemd-networkd 接続は、事前定義された名前付きセットにホスト IP アドレス、ネットワークプレフィックス、インターフェイスインデックスを投入するように設定できます。詳しくは systemd.network(5) § [ADDRESS SECTION OPTIONS]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
	}

}
ヒント systemd-networkd を使用していてローカルネットワークに接続している場合、systemd.network(5) オプション 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 キーワードは nat type のチェインでのみ使用できます。
  • 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_forward1 に設定する必要があります。

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 の使用

この記事またはセクションの正確性には問題があります。
理由: nftables は legacy iptables object が読み込まれている場合に警告するため、legacy iptables と nftables を同時に使うことが「完全に問題なく動作する」とは言えません。 (議論: トーク:Nftables#)

古い iptables 言語は Linux ドキュメントでは依然としてかなり支配的であり、Docker のネットワークなど、iptables に依存して動作するものも少なくありません。legacy iptables と nftables を同時に使うことも可能ではありますが、iptables-nft の変換を使うことが推奨されます。理由は次のとおりです:

  • すべてを新しく、より効率的で、ロックを必要としないフレームワークの同じ場所に配置します。
  • 競合をチェックします。

nftables で古い iptables 言語を使用する方法は 2 つあります:

  • iptables-translateiptables-restore-translate (ip6tablesebtables なども同様) は、iptables 言語を受け取り nft 言語を出力します。実行中の nft 設定は変更しません。xtables-translate(8) を参照してください。
後で保守したい設定については、-translate ツールを使い、その結果のコードを既存のルールに統合するのがよいでしょう。例えば、シンプルなステートフルファイアウォールやインターネット上で便利なものを見つけた場合、それらを nft 設定に入れられるように変換できます。
  • iptablesiptables-restore (ip6tables なども同様) は上記の変換を使い、さらに実行中の nft 設定に反映します。通常の iptables と同じように統計情報も提供します。xtables-nft(8) を参照してください。
これらのコマンドは、やるべきことを考えれば十分にうまく動作します。単純な使い方では「そのまま動く」はずですが、ときどき手動でのデバッグが必要になることがあります。
ノート translator は iptables 言語の大部分をカバーしていますが、すべてではありません。一部の iptables ルールは組み合わせて動作し、translator が正しく変換するには文脈が必要です。そのため、変換結果が空になる行があっても慌てないでください。

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 インターフェイスのファイアウォールとポートフォワーディングを干渉することなくセットアップできるようになります。

参照