「Nftables」の版間の差分
Kusanaginoturugi (トーク | 投稿記録) →使用方法: 記事を更新 |
Kusanaginoturugi (トーク | 投稿記録) →設定: 記事の更新 |
||
| 57行目: | 57行目: | ||
== 設定 == |
== 設定 == |
||
nftables |
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 '' |
# nft list table ''family_type'' ''table_name'' |
||
例えば |
例えば、{{ic|inet}} family の {{ic|my_table}} テーブルのすべてのルールを一覧表示するには: |
||
# nft list table inet |
# nft list table inet my_table |
||
==== テーブルの削除 ==== |
==== テーブルの削除 ==== |
||
| 127行目: | 121行目: | ||
テーブルを削除するには: |
テーブルを削除するには: |
||
# nft delete table '' |
# nft delete table ''family_type'' ''table_name'' |
||
テーブル |
これにより、テーブル内のすべてのチェインが破棄されます。 |
||
==== テーブルのクリア ==== |
==== テーブルのクリア ==== |
||
| 135行目: | 129行目: | ||
テーブルから全てのルールを消去するには: |
テーブルから全てのルールを消去するには: |
||
# nft flush table '' |
# nft flush table ''family_type'' ''table_name'' |
||
===チェイン=== |
===チェイン=== |
||
| 143行目: | 137行目: | ||
チェインには2つのタイプがあります。''base'' チェインはネットワークスタックからのパケットのエントリポイントとなります。フックの値を指定することができます。''regular'' チェインはジャンプターゲットとして使用することができます。 |
チェインには2つのタイプがあります。''base'' チェインはネットワークスタックからのパケットのエントリポイントとなります。フックの値を指定することができます。''regular'' チェインはジャンプターゲットとして使用することができます。 |
||
以下のコマンドで使っている {{ic|'' |
以下のコマンドで使っている {{ic|''family_type''}} は全て任意であり、指定しなかった場合は {{ic|ip}} が使われます。 |
||
==== チェインの作成 ==== |
==== チェインの作成 ==== |
||
===== |
===== 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 |
# 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行目: | ||
チェインを編集したいときは、チェインの名前を指定して変更したいルールを定義します: |
チェインを編集したいときは、チェインの名前を指定して変更したいルールを定義します: |
||
# |
# 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 |
# nft chain inet my_table my_input '{ policy drop ; }' |
||
==== チェインの削除 ==== |
==== チェインの削除 ==== |
||
| 199行目: | 197行目: | ||
チェインを削除するには: |
チェインを削除するには: |
||
# nft delete chain '' |
# nft delete chain ''family_type'' ''table_name'' ''chain_name'' |
||
削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。 |
削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。 |
||
| 207行目: | 205行目: | ||
チェインからルールを消去するには: |
チェインからルールを消去するには: |
||
# nft flush chain '' |
# nft flush chain ''family_type'' ''table_name'' ''chain_name'' |
||
=== ルール === |
=== ルール === |
||
| 219行目: | 217行目: | ||
チェインにルールを追加するには: |
チェインにルールを追加するには: |
||
# nft add rule '' |
# nft add rule ''family_type'' ''table_name'' ''chain_name'' handle ''handle_value'' ''statement'' |
||
ルールは {{ic|'' |
ルールは {{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|'' |
{{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}} はハンドルを出力するようになります。 |
|||
個々のルールはハンドルを使わないと削除することができません。{{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 |
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 |
|||
テーブル内のすべてのチェインは {{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 コマンドの実装を提供します。ただし、古い iptables-legacy ツールで作成されたルールは別のオブジェクトであり、それらが存在する場合、iptables は警告を表示します。フロントエンド
- firewalld (firewall-cmd) — ネットワークとファイアウォールゾーンの設定、およびファイアウォールルールの設定と構成を行うデーモンおよびコンソールインターフェイス。
- nft-blackhole — 国別およびブラックリストによって nftables で IP をブロックするスクリプト / デーモン。
- ufw — Ufw は Uncomplicated Firewall の略で、netfilter ファイアウォールを管理するためのプログラムです。
- reaction — プログラムの出力から繰り返し出現するパターンをスキャンし、アクションを実行するデーモン。fail2ban の軽量な代替です。
使用方法
nftables は、コマンドラインで作成された一時的なルールと、ファイルから読み込まれた、またはファイルに保存された永続的なルールを区別しません。
すべてのルールは nft コマンドラインユーティリティを使って作成または読み込む必要があります。
使用方法については #設定 セクションを参照してください。
現在の ruleset は次のコマンドで表示できます:
# nft list ruleset
すべての ruleset を削除し、システムにファイアウォールがない状態にします:
# nft flush ruleset
nftables.service を再起動することで、/etc/nftables.conf から ruleset を読み込みます。
シンプルなファイアウォール
nftables には、/etc/nftables.conf ファイルに保存されたシンプルで安全なファイアウォール設定が付属しています。
nftables.service は、起動/有効化されたときに、そのファイルからルールを読み込みます。
設定
nftables ユーザースペースユーティリティ nft は、ruleset をカーネルに渡す前に、ルールセット評価の大部分を実行します。ルールはチェインに格納され、チェインはテーブルに格納されます。以下のセクションでは、これらの構造を作成および変更する方法を示します。
ファイルから入力を読み込むには、-f/--file オプションを使用します:
# nft --file filename
既に読み込まれているルールは自動的にはフラッシュされないことに注意してください。
すべてのコマンドの完全な一覧については nft(8) を参照してください。
テーブル
テーブルはチェインを保持します。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルの数や名前はユーザーが自由に決めることができますが、各テーブルにはアドレスファミリーをひとつしか保持することができません。5つのファミリーのうち指定したファミリーのパケットにだけ適用されます:
| nftables ファミリー | iptables ユーティリティ |
|---|---|
| ip | iptables |
| ip6 | ip6tables |
| inet | iptables と ip6tables |
| arp | arptables |
| bridge | ebtables |
ip (IPv4) がデフォルトのファミリーです。特に指定がなければ ip が使われます。
IPv4 と IPv6 の両方に適用されるルールを作成するには inet を使います。inet を使うには Linux 3.15 以上が必要で、ip と ip6 ファミリーを統一してルールを簡単に定義できます。
アドレスフファミリーの完全な定義は nft(8) の ADDRESS FAMILIES セクションを参照してください。
以下で例示しているコマンドの family は全て任意であり、指定しなかった場合は ip が使われます。
テーブルの作成
以下のコマンドで新しいテーブルが追加されます:
# nft add table family table
テーブルの一覧表示
全てのテーブルを表示するには:
# nft list tables
テーブル内のチェインとルールの表示
指定したテーブルの全てのチェインとルールを表示するには:
# nft list table family_type table_name
例えば、inet family の my_table テーブルのすべてのルールを一覧表示するには:
# nft list table inet my_table
テーブルの削除
テーブルを削除するには:
# nft delete table family_type table_name
これにより、テーブル内のすべてのチェインが破棄されます。
テーブルのクリア
テーブルから全てのルールを消去するには:
# nft flush table family_type table_name
チェイン
チェインの用途はルールを保持することです。iptables のチェインと違って、nftables には初めから組み込まれているチェインはありません。そのためチェインが netfilter フレームワークにあるタイプやフックをどれも使わない場合、iptables とは異なりチェインを通り抜けるパケットは nftables の影響を受けません。
チェインには2つのタイプがあります。base チェインはネットワークスタックからのパケットのエントリポイントとなります。フックの値を指定することができます。regular チェインはジャンプターゲットとして使用することができます。
以下のコマンドで使っている family_type は全て任意であり、指定しなかった場合は ip が使われます。
チェインの作成
Base chain
base chain を追加するには、type、hook、priority の値を指定する必要があります:
# nft add chain family_type table_name chain_name '{ type chain_type hook hook_type priority priority_value ; policy policy ;}'
chain_type には filter、route、nat を指定できます。
IPv4/IPv6/Inet address family では、hook_type に prerouting、input、forward、output、postrouting を指定できます。サポートされる family_type、chain_type、hook_type の組み合わせ一覧については nft(8) § CHAINS を参照してください。
priority_value には priority 名または整数値を指定できます。標準 priority 名と値の一覧については nft(8) § CHAINS を参照してください。数値が小さいチェインほど先に処理され、負の値も使用できます。[5]
任意で、base chain には policy (drop またはデフォルトの accept) を指定できます。これにより、チェイン内のルールで明示的に accept または refuse されなかったパケットに何が起こるかを定義します。
例えば、入力パケットをフィルタリングする base chain を追加するには:
# nft add chain inet my_table my_chain '{ type filter hook input priority 0; }'
上記のいずれでも add を create に置き換えると、新しいチェインを追加しますが、チェインが既に存在する場合はエラーを返します。
Regular chain
次のコマンドは、table_name という名前のテーブルに chain_name という名前の regular chain を追加します:
# nft add chain family_type table_name chain_name
例えば、inet address family の my_table テーブルに my_tcp_chain という regular chain を追加するには:
# nft add chain inet my_table my_tcp_chain
チェインの一覧表示
次のコマンドは、family_type のすべてのチェインを、ルールなしで一覧表示します (#ルールの一覧表示 を参照):
# nft list chains family_type
例えば、次のコマンドは IPv6 のチェインを一覧表示します:
# nft list chains ip6
family_type を省略した場合、すべてのチェインが表示されます。
チェインの編集
チェインを編集したいときは、チェインの名前を指定して変更したいルールを定義します:
# nft chain family_type table_name chain_name '{ [ type chain_type hook hook_type device device_name priority priority_value ; policy policy_type ; ] }'
例えば、デフォルトテーブル内の my_input チェインの policy を accept から drop に変更するには:
# nft chain inet my_table my_input '{ policy drop ; }'
チェインの削除
チェインを削除するには:
# nft delete chain family_type table_name chain_name
削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。
チェインのルールを消去
チェインからルールを消去するには:
# nft flush chain family_type table_name chain_name
ルール
ルールは表現または宣言から構成され、チェインの中に格納されます。
ルールの追加
チェインにルールを追加するには:
# nft add rule family_type table_name chain_name handle handle_value statement
ルールは handle_value の位置に追加されます。これは任意です。指定しない場合、ルールはチェインの末尾に追加されます。
ルール handle を確認するには、任意の有効な list コマンドに --handle スイッチを追加する必要があります。このスイッチにより、nft は出力に handle を表示します。--numeric 引数は、未解決の IP アドレスなど、一部の数値出力を確認するのに便利です。
# nft --handle --numeric list chain inet my_table my_input
table inet my_table {
chain input {
type filter hook input priority 0;
ip saddr 127.0.0.1 accept # handle 10
}
}
指定位置の前にルールを挿入するには:
# nft insert rule family_type table_name chain_name handle handle_value statement
handle_value が指定されていない場合、ルールはチェインの先頭に挿入されます。
表現
statement にはマッチする表現と判断宣言が入ります。判断宣言には accept, drop, queue, continue, return, jump chain, goto chain などが存在します。判断宣言以外の宣言も指定できます。詳しくは nft(8) を参照してください。
nftables では様々な表現を使うことができ、ほとんどは、iptables と対応するようになっています。一番大きな違いは汎用的なマッチと暗黙的なマッチが存在しないことです。汎用的なマッチとは、--protocol や --source のように、いつでも使うことができるマッチで、暗黙的なマッチとは、--sport のように、特定のプロトコルでしか使えないマッチのことです。
以下は利用できるマッチの一部です:
- meta (メタプロパティ。例: インターフェイス)
- icmp (ICMP プロトコル)
- icmpv6 (ICMPv6 プロトコル)
- ip (IP プロトコル)
- ip6 (IPv6 プロトコル)
- tcp (TCP プロトコル)
- udp (UDP プロトコル)
- sctp (SCTP プロトコル)
- ct (接続のトラッキング)
以下はマッチ引数の一部です (完全なリストは nft(8) を見て下さい):
meta: oif <output interface INDEX> iif <input interface INDEX> oifname <output interface NAME> iifname <input interface NAME> (oif and iif accept string arguments and are converted to interface indexes) (oifname and iifname are more dynamic, but slower because of string matching) icmp: type <icmp type> icmpv6: type <icmpv6 type> ip: protocol <protocol> daddr <destination address> saddr <source address> ip6: daddr <destination address> saddr <source address> tcp: dport <destination port> sport <source port> udp: dport <destination port> sport <source port> sctp: dport <destination port> sport <source port> ct: state <new | established | related | invalid>
ある意味では、iif と oif に対する iifname と oifname の違いは、static と dynamic の違いに似ています。または、プログラミング概念でいう definition と declaration、あるいは early binding と delayed binding に似ています。使用例と追加説明へのリンクについては [6] を参照してください。
ルールの一覧表示
次のコマンドはチェイン内のすべてのルールを一覧表示します:
# nft list chain family_type table_name chain_name
例えば、my_table という inet テーブル内の my_output というチェインのルールを一覧表示するには:
# nft list chain inet my_table my_output
削除
個々のルールはハンドルを使わないと削除することができません。nft --handle list コマンドを使うことでルールのハンドルを確認できます。例えば次のような場合:
# nft --handle --numeric list chain inet my_table my_input
table inet my_table {
chain input {
type filter hook input priority 0;
ip saddr 127.0.0.1 accept # handle 10
}
}
次のコマンドで削除できます:
# nft delete rule inet my_table my_input handle 10
テーブル内のすべてのチェインは nft flush table コマンドでフラッシュできます。個別のチェインは nft flush chain または nft delete rule コマンドでフラッシュできます。
# nft flush table table_name # nft flush chain family_type table_name chain_name # nft delete rule family_type table_name chain_name
最初のコマンドは、ip table_name テーブル内のすべてのチェインをフラッシュします。2 番目のコマンドは、family_type table_name テーブル内の chain_name チェインをフラッシュします。3 番目のコマンドは、family_type table_name テーブル内の chain_name チェインのすべてのルールを削除します。
セット
セットには名前付きセットと匿名セットがあります。セットは 1 つ以上の要素で構成され、要素はカンマで区切られ、波括弧で囲まれます。匿名セットはルールに埋め込まれ、更新できません。ルールを削除して再追加する必要があります。例えば、次の dports セットから "http" だけを削除することはできません:
# nft add rule ip6 filter input tcp dport {telnet, http, https} accept
名前付きセットは更新でき、型付けやフラグ付けが可能です。sshguard は、ブロックされたホストの IP アドレスに名前付きセットを使用します。
table ip sshguard {
set attackers {
type ipv4_addr
flags interval
elements = { 1.2.3.4 }
}
セットに要素を追加または削除するには、次のようにします:
# nft add element ip sshguard attackers { 5.6.7.8/32 }
# nft delete element ip sshguard attackers { 1.2.3.4/32 }
ipv4_addr 型には CIDR netmask を含められることに注意してください (ここでの /32 は必須ではありませんが、完全性のために含めています)。また、ここで TABLE ip sshguard { SET attackers } によって定義されたセットは、ip sshguard attackers として参照されることにも注意してください。
NFTSet= の説明と #systemd-networkd を使った動的名前付きセット の例を参照してください。アトミックリロード
現在のルールセットをフラッシュする:
# echo "flush ruleset" > /tmp/nftables
現在のルールセットをダンプする:
# nft list ruleset >> /tmp/nftables
/tmp/nftables を編集して次のコマンドで変更を適用:
# nft -f /tmp/nftables
サンプル
ワークステーション
/etc/nftables.conf
flush ruleset
table inet 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 インターフェイスのファイアウォールとポートフォワーディングを干渉することなくセットアップできるようになります。