コンテンツにスキップ

「Nftables」の版間の差分

提供: ArchWiki
削除された内容 追加された内容
使用方法: 記事を更新
設定: 記事の更新
57行目: 57行目:
== 設定 ==
== 設定 ==


nftables ユーザースペースユーティリティ {{ic|nft}} は現在カーネルのためルールセットを処理前にほとんどのルールセット評価を行ます。ルールはチェインに保存され、チェインはテーブルに保存されます。下のセクションではルールを作成・編集する方法を説明します。
nftables ユーザースペースユーティリティ {{ic|nft}} は、ruleset をカーネルにす前にルールセット評価の大部分ます。ルールはチェインに格納され、チェインはテーブルに格納されます。下のセクションでは、これらの構造を作成および変更する方法をします。


ファイルから入力を読み込むには、{{ic|-f}}/{{ic|--file}} オプションを使用します:
下のセクションで行った変更は全て一時的なものになります。変更を永続化するにはルールセットを {{ic|/etc/nftables.conf}} に保存してください (ルールセットは {{ic|nftables.service}} によって読み込まれます):


# nft --file ''filename''
# nft list ruleset > /etc/nftables.conf


既に読み込まれているルールは'''自動的には'''フラッシュされないことに注意してください。
{{Note|{{ic|nft list}} は変数の定義を出力しません。{{ic|/etc/nftables.conf}} に何か記述していた場合、定義は失われます。ルールによって使われていた変数は変数の値に置き換えられます。}}


すべてのコマンドの完全な一覧については {{man|8|nft}} を参照してください。
ファイルから入力するには {{ic|-f}} フラグを使用します:

# nft -f ''filename''

ロード済みのルールは自動的に消去されることはないので注意してください。

利用可能なコマンドの一覧は {{man|8|nft}} を参照してください。


===テーブル===
===テーブル===
107行目: 101行目:
# nft add table ''family'' ''table''
# nft add table ''family'' ''table''


==== テーブルの表示 ====
==== テーブルの一覧表示 ====


全てのテーブルを表示するには:
全てのテーブルを表示するには:
117行目: 111行目:
指定したテーブルの全てのチェインとルールを表示するには:
指定したテーブルの全てのチェインとルールを表示するには:


# nft list table ''family'' ''table''
# nft list table ''family_type'' ''table_name''


例えば {{ic|inet}} ファミリーの {{ic|filter}} テーブルのルールを全て表示するには:
例えば{{ic|inet}} family の {{ic|my_table}} テーブルのすべてのルールを一覧表示するには:


# nft list table inet filter
# nft list table inet my_table


==== テーブルの削除 ====
==== テーブルの削除 ====
127行目: 121行目:
テーブルを削除するには:
テーブルを削除するには:


# nft delete table ''family'' ''table''
# nft delete table ''family_type'' ''table_name''


テーブルチェインが全く存在しない場合にのみ削除できます。
これにより、テーブル内のすべてのチェインが破棄されます。


==== テーブルのクリア ====
==== テーブルのクリア ====
135行目: 129行目:
テーブルから全てのルールを消去するには:
テーブルから全てのルールを消去するには:


# nft flush table ''family'' ''table''
# nft flush table ''family_type'' ''table_name''


===チェイン===
===チェイン===
143行目: 137行目:
チェインには2つのタイプがあります。''base'' チェインはネットワークスタックからのパケットのエントリポイントとなります。フックの値を指定することができます。''regular'' チェインはジャンプターゲットとして使用することができます。
チェインには2つのタイプがあります。''base'' チェインはネットワークスタックからのパケットのエントリポイントとなります。フックの値を指定することができます。''regular'' チェインはジャンプターゲットとして使用することができます。


以下のコマンドで使っている {{ic|''family''}} は全て任意であり、指定しなかった場合は {{ic|ip}} が使われます。
以下のコマンドで使っている {{ic|''family_type''}} は全て任意であり、指定しなかった場合は {{ic|ip}} が使われます。


==== チェインの作成 ====
==== チェインの作成 ====


===== Regular チェイン =====
===== Base chain =====


base chain を追加するには、type、hook、priority の値を指定する必要があります:
以下のコマンドは {{ic|''table''}} という名前のテーブルに {{ic|''chain''}} という名前のレギュラーチェインを追加します:


# nft add chain ''family_type'' ''table_name'' ''chain_name'' '{ type ''chain_type'' hook ''hook_type'' priority ''priority_value'' ; policy ''policy'' ;}'
# nft add chain ''family'' ''table'' ''chain''


{{ic|''chain_type''}} には {{ic|filter}}、{{ic|route}}、{{ic|nat}} を指定できます。
例えば、{{ic|inet}} アドレスファミリーの {{ic|filter}} テーブルに {{ic|tcpchain}} という名前のレギュラーチェインを追加するには:


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}} を参照してください。
# nft add chain inet filter tcpchain


{{ic|''priority_value''}} には priority 名または整数値を指定できます。標準 priority 名と値の一覧については {{man|8|nft|CHAINS}} を参照してください。数値が小さいチェインほど先に処理され、負の値も使用できます。[https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_types]
===== Base チェイン =====


任意で、base chain には {{ic|''policy''}} ({{ic|drop}} またはデフォルトの {{ic|accept}}) を指定できます。これにより、チェイン内のルールで明示的に accept または refuse されなかったパケットに何が起こるかを定義します。
ベースチェインを追加するにはフックとプライオリティの値を指定します:


例えば、入力パケットをフィルタリングする base chain を追加するには:
# nft add chain ''family'' ''table'' ''chain'' { type ''type'' hook ''hook'' priority ''priority'' \; }


# nft add chain inet my_table my_chain '{ type filter hook input priority 0; }'
{{ic|''type''}} は {{ic|filter}}, {{ic|route}}, {{ic|nat}} のどれかから選ぶことができます。


上記のいずれでも {{ic|add}} を {{ic|create}} に置き換えると、新しいチェインを追加しますが、チェインが既に存在する場合はエラーを返します。
IPv4/IPv6/Inet アドレスファミリーでは {{ic|''hook''}} は {{ic|prerouting}}, {{ic|input}}, {{ic|forward}}, {{ic|output}}, {{ic|postrouting}} のどれかになります。他のファミリーのフックについては {{man|8|nft}} を参照してください。


===== Regular chain =====
{{ic|''priority''}} には整数値を指定します。低い値のチェインが先に処理され、負の値を指定することもできます [https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_types]。


次のコマンドは、{{ic|''table_name''}} という名前のテーブルに {{ic|''chain_name''}} という名前の regular chain を追加します:
例えば、input パケットをフィルタリングするベースチェインを追加するには:


# nft add chain inet filter input { type filter hook input priority 0\; }
# nft add chain ''family_type'' ''table_name'' ''chain_name''


例えば、{{ic|inet}} address family の {{ic|my_table}} テーブルに {{ic|my_tcp_chain}} という regular chain を追加するには:
{{ic|add}} を {{ic|create}} に置き換えると、チェインが既に存在するときにエラーが返ってくるようになります。


# nft add chain inet my_table my_tcp_chain
==== ルールの表示 ====


以下のコマンドでチェインの全てのルールを表示できます:
==== チェインの一覧表示 ====


次のコマンドは、''family_type'' のすべてのチェインを、ルールなしで一覧表示します ([[#ルールの一覧表示]] を参照):
# nft list chain ''family'' ''table'' ''chain''


# nft list chains ''family_type''
例えば、{{ic|filter}} という名前の {{ic|inet}} テーブルに存在する {{ic|output}} という名前のチェインのルールを表示するには:


例えば、次のコマンドは IPv6 のチェインを一覧表示します:
# nft list chain inet filter output

# nft list chains ip6

family_type を省略した場合、すべてのチェインが表示されます。


==== チェインの編集 ====
==== チェインの編集 ====
189行目: 187行目:
チェインを編集したいときは、チェインの名前を指定して変更したいルールを定義します:
チェインを編集したいときは、チェインの名前を指定して変更したいルールを定義します:


# <nowiki>nft chain <family> <table> <chain> { [ type <type> hook <hook> device <device> priority <priority> \; policy <policy> \; ] }</nowiki>
# nft chain ''family_type table_name chain_name'' '{ [ type ''chain_type'' hook ''hook_type'' device ''device_name'' priority ''priority_value'' ; policy ''policy_type'' ; ] }'


例えば、デフォルトテーブルの input チェインポリシー"accept" から "drop" に変更したい場合:
例えば、デフォルトテーブル{{ic|my_input}} チェインの policy {{ic|accept}} から {{ic|drop}} に変更するには:


# nft chain inet filter input { policy drop \; }
# nft chain inet my_table my_input '{ policy drop ; }'


==== チェインの削除 ====
==== チェインの削除 ====
199行目: 197行目:
チェインを削除するには:
チェインを削除するには:


# nft delete chain ''family'' ''table'' ''chain''
# nft delete chain ''family_type'' ''table_name'' ''chain_name''


削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。
削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。
207行目: 205行目:
チェインからルールを消去するには:
チェインからルールを消去するには:


# nft flush chain ''family'' ''table'' ''chain''
# nft flush chain ''family_type'' ''table_name'' ''chain_name''


=== ルール ===
=== ルール ===
219行目: 217行目:
チェインにルールを追加するには:
チェインにルールを追加するには:


# nft add rule ''family'' ''table'' ''chain'' ''position'' ''statement''
# nft add rule ''family_type'' ''table_name'' ''chain_name'' handle ''handle_value'' ''statement''


ルールは {{ic|''position''}} に追加されます。位置は指定しなくてもかまません。指定しなかった場合、ルールはチェインの末尾に追加されます。
ルールは {{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>
# nft insert rule ''family'' ''table'' ''chain'' ''position'' ''statement''
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|''position''}} 指定かった場合、ルールはチェインの一番前追加されます。
{{ic|''handle_value''}} 指定されてい場合、ルールはチェインの先頭挿入されます。


===== 表現 =====
===== 表現 =====
287行目: 296行目:
ct:
ct:
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] を参照してください。

==== ルールの一覧表示 ====

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

# nft list chain ''family_type'' ''table_name'' ''chain_name''

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

# nft list chain inet my_table my_output


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


以下ではルールハンドルを確認してルールを削除しています。未解決の IP アドレスのような、数字の出力を表示するとき{{ic|--number}} 引数を使うと良いしょう
個々のルールハンドルを使わないと削除するがでません。{{ic|nft --handle list}} コマンドを使うとでルールのハンドルを確認できます例えば次のような場合:

{{hc|# nft --handle --numeric list chain filter input|2=
{{hc|# nft --handle --numeric list chain inet my_table my_input|2=<nowiki>
<nowiki>
table ip fltrTable {
table inet my_table {
chain input {
chain input {
type filter hook input priority 0;
type filter hook input priority 0;
300行目: 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



2026年5月27日 (水) 13:06時点における版

関連記事

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 filter {
        chain input {
                type filter hook input priority 0;

                # accept any localhost traffic
                iif lo accept

                # accept traffic originated from us
                ct state established,related accept

                # activate the following line to accept common local services
                #tcp dport { 22, 80, 443 } ct state new accept

                # accept neighbour discovery otherwise IPv6 connectivity breaks.
                ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit,  nd-router-advert, nd-neighbor-advert } accept

                # count and drop any other traffic
                counter drop
        }
}

シンプルな IPv4/IPv6 ファイアウォール

firewall.rules
# A simple firewall

flush ruleset

table inet filter {
	chain input {
		type filter hook input priority 0; policy drop;

		# established/related connections
		ct state established,related accept

		# invalid connections
		ct state invalid drop
		
		# loopback interface
		iif lo accept

		# ICMP
		# 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

		# SSH (port 22)
		tcp dport ssh accept

		# HTTP (ports 80 & 443)
		tcp dport { http, https } accept
	}

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

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

}

レート制限 IPv4/IPv6 ファイアウォール

firewall.2.rules
table inet filter {
	chain input {
		type filter hook input priority 0; policy drop;

		# no ping floods:
		ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 10/second accept
		ip protocol icmp icmp type echo-request limit rate 10/second accept

		ct state established,related accept
		ct state invalid drop

		iif lo accept

		# avoid brute force on ssh:
		tcp dport ssh limit rate 15/minute accept

	}

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

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

}

ジャンプ

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

jump.rules
table inet filter {
    chain web {
        tcp dport http accept
        tcp dport 8080 accept
    }
    chain input {
        type filter hook input priority 0;
        ip saddr 10.0.2.0/24 jump web
        drop
    }
}

インターフェイスによってルールを変える

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

table inet filter {
  chain input { # this chain serves as a dispatcher
    type filter hook input priority 0;

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

    reject with icmp type port-unreachable # refuse traffic from all other interfaces
  }
  chain input_enp2s0 { # rules applicable to public interface interface
    ct state {established,related} accept
    ct state invalid drop
    udp dport bootpc accept
    tcp dport bootpc accept
    reject with icmp type port-unreachable # all other traffic
  }
  chain input_enp3s0 {
    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 icmp type port-unreachable # all other traffic
  }
  chain ouput { # we let everything out
    type filter hook output priority 0;
    accept
  }
 }

もしくは iifname ステートメントを特定のインターフェイスで使用して、他のインターフェイスについてはデフォルトルールを設定するという方法もあります。

マスカレード

nftables には特殊なキーワード masquerade が存在し、送信元アドレスが自動的に出力インターフェイスのアドレスに設定されます (ソース)。ルーターのインターフェイスが多数の ISP に接続されているときなど、インターフェイスの IP アドレスが一定でない場合に有用です。通常は、インターフェイスの IP アドレスが変わるたびにネットワークアドレス変換 (NAT) のルールを更新する必要があります。

masquerade を使用するには:

  • カーネルコンフィグで以下のマスカレード設定が有効になっている必要があります。
CONFIG_NFT_MASQ=m
  • masquerade キーワードは nat タイプのチェインでのみ使うことができます。
  • マスカレードは一種のソース NAT であり、出力パスでのみ機能します。

2つのインターフェイスが存在し nsp3s0 が LAN に接続され、enp2s0 がインターネットに接続されているマシンでの設定例:

table inet my_nat {
  chain my_masquerade {
    type nat hook postrouting priority srcnat;
    oifname "enp2s0" masquerade
  }
}

テーブルタイプがinetであるため、IPv4パケットとIPv6パケットの両方がマスカレードされます。IPv4パケットのみをマスカレードしたい場合(IPv6のアドレス空間が拡張されているためNATが不要)、oifname "enp2s0"の前にmeta nfproto ipv4を追記するか、テーブルタイプをipに変更してください。

ヒントとテクニック

シンプルなステートフルファイアウォール

シンプルなステートフルファイアウォールの記事も参照してください。

シングルマシン

現在のルールセットを消去:

# 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 を見てください。

トラブルシューティング

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

参照