「Nftables」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(1版 をインポートしました)
(マークアップの訂正 (""使用しない"" -> '''使用しない''))
 
(8人の利用者による、間の18版が非表示)
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 フレームワークを置き換える netfilter のプロジェクトです。新しいパケットフィルタリングフレームワーク、新しいユーザースペースユーティリティ (nft)、そして ip- と ip6tables の互換レイヤーを提供します。現行のフック、接続追跡システム、ユーザースペースのキューイングコンポーネント、そして netfilter のログサブシステムを使っています。
   
最初のリリースは Linux 3.13 から使うことが可能で、このカーネルは現在 [core] リポジトリに入っています ({{Pkg|linux}})。(ユーザースペースコンポーネントの) nftables は [extra] リポジトリから利用でき ({{Pkg|nftables}})、[[Arch User Repository|AUR]] には {{AUR|nftables-git}} パッケージがあります。
 
 
==概要==
 
 
nftables は3つのメインコンポーネントから構成されています: カーネルの実装、libnl netlink communication そして nftables ユーザースペースフロントエンド。カーネルは netlink の設定インターフェイスだけでなく、小さなクラス言語インタプリタを使用するランタイムのルールセットの評価も提供します。libnl にはカーネルと通信するためのローレベルな関数が含まれています。nftables フロントエンドはユーザーが対話するものです。
 
nftables は3つのメインコンポーネントから構成されています: カーネルの実装、libnl netlink communication そして nftables ユーザースペースフロントエンド。カーネルは netlink の設定インターフェイスだけでなく、小さなクラス言語インタプリタを使用するランタイムのルールセットの評価も提供します。libnl にはカーネルと通信するためのローレベルな関数が含まれています。nftables フロントエンドはユーザーが対話するものです。
   
  +
[https://wiki.nftables.org/wiki-nftables/index.php/Main_Page nftables の公式 wiki] には詳しい情報が載っています。
==nft==
 
nftables のユーザースペースユーティリティ {{ic|nft}} は現在カーネルのためにルールセットを処理する前にほとんどのルールセットの評価を行います。そのため、nftables はデフォルトのテーブルやチェインを提供していません。しかしながらユーザーが iptables のような設定をエミュレートすることが可能です。
 
   
  +
== インストール ==
ifconfig や iproute2 と同じような感じで動作します。iptables のように引数のスイッチを使う代わりに、長く構造化された連続のコマンドになります。例えば:
 
nft add rule ip6 filter input ip6 saddr ::1 accept
 
{{ic|add}} はコマンドです。{{ic|rule}} は {{ic|add}} のサブコマンドです。{{ic|ip6}} は {{ic|rule}} の引数で、ip6 ファミリーを使うことを宣言しています。{{ic|filter}} と {{ic|input}} は {{ic|rule}} の引数で、それぞれ使用するテーブルとチェインを指定しています。残りはルールの定義で、マッチ ({{ic|ip}}) とパラメータ ({{ic|saddr}})、パラメータの引数 ({{ic|::1}}) そしてジャンプ ({{ic|accept}}) からなります。
 
   
  +
nftables のユーザーランドユーティリティは {{Pkg|nftables}} パッケージで利用できます。開発版の {{AUR|nftables-git}} パッケージも存在します。
以下は nft で利用できるコマンドの不完全なリストです:
 
<nowiki>
 
list
 
tables [family]
 
table [family] <name>
 
chain [family] <table> <name>
 
   
  +
{{Tip|ほとんどの [[iptables#Front-ends|iptables フロントエンド]] はnftables の直接的または間接的なサポートを備えていませんが、導入することは可能です。[https://www.spinics.net/lists/netfilter/msg58215.html] nftables と iptables の両方をサポートするグラフィカルなフロントエンドとしては、[[firewalld]] があります。[https://firewalld.org/2018/07/nftables-backend]}}
add
 
table [family] <name>
 
chain [family] <table> <name> [chain definitions]
 
rule [family] <table> <chain> <rule definition>
 
   
  +
== 使用方法 ==
table [family] <name> (shortcut for `add table`)
 
   
  +
nftables ではコマンドラインで作成される一時的なルールと、ファイルに保存して読み込まれる永続的なルールを区別していません。デフォルトファイルの {{ic|/etc/nftables.conf}} には "inet filter" という名前のシンプルな ipv4/ipv6 ファイアウォールテーブルが既に記述されています。
insert
 
rule [family] <table> <chain> <rule definition>
 
   
  +
{{ic|nftables.service}} を[[起動]]・[[有効化]]してください。
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}} になります。
 
   
  +
# nft list ruleset
==テーブル==
 
  +
テーブルの用途はチェインを保持することです。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルは指定の4つのファミリーのうちどれか一つを持つことができ、それによって様々な iptables のユーティリティを一つに統一します:
 
  +
=== シンプルなファイアウォール ===
  +
  +
{{Pkg|nftables}} には、{{ic|/etc/nftables.conf}} ファイルに保存されたシンプルで安全なファイアウォール設定が付属しています。
  +
  +
{{ic|nftables.service}} は、[[起動]]または[[有効化]]時に、このファイルからルールを読み込みます。
  +
  +
== 設定 ==
  +
  +
nftables のユーザースペースユーティリティ {{ic|nft}} は現在カーネルのためにルールセットを処理する前にほとんどのルールセットの評価を行います。ルールはチェインに保存され、チェインはテーブルに保存されます。下のセクションではルールを作成・編集する方法を説明します。
  +
  +
下のセクションで行った変更は全て一時的なものになります。変更を永続化するにはルールセットを {{ic|/etc/nftables.conf}} に保存してください (ルールセットは {{ic|nftables.service}} によって読み込まれます):
  +
  +
# nft list ruleset > /etc/nftables.conf
  +
  +
{{Note|{{ic|nft list}} は変数の定義を出力しません。{{ic|/etc/nftables.conf}} に何か記述していた場合、定義は失われます。ルールによって使われていた変数は変数の値に置き換えられます。}}
  +
  +
ファイルから入力するには {{ic|-f}} フラグを使用します:
  +
  +
# nft -f ''filename''
  +
  +
ロード済みのルールは自動的に消去されることはないので注意してください。
  +
  +
利用可能なコマンドの一覧は {{man|8|nft}} を参照してください。
  +
  +
===テーブル===
  +
  +
テーブルは[[#チェイン|チェイン]]を保持します。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルの数や名前はユーザーが自由に決めることができますが、各テーブルにはアドレスファミリーをひとつしか保持することができません。5つのファミリーのうち指定したファミリーのパケットにだけ適用されます:
   
 
{| class="wikitable"
 
{| class="wikitable"
56行目: 62行目:
 
|-
 
|-
 
| ip6 || ip6tables
 
| ip6 || ip6tables
  +
|-
  +
| inet || iptables と ip6tables
 
|-
 
|-
 
| arp || arptables
 
| arp || arptables
62行目: 70行目:
 
|}
 
|}
   
{{ic|ip}} がデフォルトのファミリーです。Linux 3.15 では ip と ip6 ファミリーを統一してルールを簡単に定義できるようにする5番目のファミリー予定さています。
+
{{ic|ip}} (IPv4) がデフォルトのファミリーです。特に指定がなければ {{ic|ip}}使われます。
  +
  +
IPv4 と IPv6 の両方に適用されるルールを作成するには {{ic|inet}} を使います。{{ic|inet}} を使うには Linux 3.15 以上が必要で、{{ic|ip}} と {{ic|ip6}} ファミリーを統一してルールを簡単に定義できます。
  +
  +
{{Note|{{ic|inet}} は {{ic|nat}} タイプのチェインでは使えず、{{ic|filter}} タイプのチェインを使う必要があります ([https://www.spinics.net/lists/netfilter/msg56411.html ソース])。}}
  +
  +
アドレスフファミリーの完全な定義は {{man|8|nft}} の {{ic|ADDRESS FAMILIES}} セクションを参照してください。
  +
  +
以下で例示しているコマンドの {{ic|''family''}} は全て任意であり、指定しなかった場合は {{ic|ip}} が使われます。
  +
  +
==== テーブルの作成 ====
  +
  +
以下のコマンドで新しいテーブルが追加されます:
  +
  +
# nft add table ''family'' ''table''
  +
  +
==== テーブルの表示 ====
  +
  +
全てのテーブルを表示するには:
   
===表示===
 
ファミリーの現在のテーブルは {{ic|nft list}} コマンドで一覧できます。
 
 
# nft list tables
 
# nft list tables
# nft list tables ip6
 
   
テーブルの名前を指定するこで完全なテルの定義を一覧できます:
+
==== テーブルチェインールの表示 ====
  +
# nft list table foo
 
  +
指定したテーブルの全てのチェインとルールを表示するには:
# nft list table ip6 foo
 
  +
  +
# nft list table ''family'' ''table''
  +
  +
例えば {{ic|inet}} ファミリーの {{ic|filter}} テーブルのルールを全て表示するには:
  +
  +
# nft list table inet filter
  +
  +
==== テーブルの削除 ====
  +
  +
テーブルを削除するには:
  +
  +
# nft delete table ''family'' ''table''
  +
  +
テーブルはチェインが全く存在しない場合にのみ削除できます。
  +
  +
==== テーブルのクリア ====
  +
  +
テーブルから全てのルールを消去するには:
  +
  +
# nft flush table ''family'' ''table''
  +
  +
===チェイン===
  +
  +
チェインの用途は[[#ルール|ルール]]を保持することです。iptables のチェインと違って、nftables には初めから組み込まれているチェインはありません。そのためチェインが netfilter フレームワークにあるタイプやフックをどれも使わない場合、iptables とは異なりチェインを通り抜けるパケットは nftables の影響を受けません。
  +
  +
チェインには2つのタイプがあります。''base'' チェインはネットワークスタックからのパケットのエントリポイントとなります。フックの値を指定することができます。''regular'' チェインはジャンプターゲットとして使用することができます。
  +
  +
以下のコマンドで使っている {{ic|''family''}} は全て任意であり、指定しなかった場合は {{ic|ip}} が使われます。
  +
  +
==== チェインの作成 ====
  +
  +
===== Regular チェイン =====
  +
  +
以下のコマンドは {{ic|''table''}} という名前のテーブルに {{ic|''chain''}} という名前のレギュラーチェインを追加します:
  +
  +
# nft add chain ''family'' ''table'' ''chain''
  +
  +
例えば、{{ic|inet}} アドレスファミリーの {{ic|filter}} テーブルに {{ic|tcpchain}} という名前のレギュラーチェインを追加するには:
  +
  +
# nft add chain inet filter tcpchain
  +
  +
===== Base チェイン =====
  +
  +
ベースチェインを追加するにはフックとプライオリティの値を指定します:
  +
  +
# nft add chain ''family'' ''table'' ''chain'' { type ''type'' hook ''hook'' priority ''priority'' \; }
  +
  +
{{ic|''type''}} は {{ic|filter}}, {{ic|route}}, {{ic|nat}} のどれかから選ぶことができます。
  +
  +
IPv4/IPv6/Inet アドレスファミリーでは {{ic|''hook''}} は {{ic|prerouting}}, {{ic|input}}, {{ic|forward}}, {{ic|output}}, {{ic|postrouting}} のどれかになります。他のファミリーのフックについては {{man|8|nft}} を参照してください。
  +
  +
{{ic|''priority''}} には整数値を指定します。低い値のチェインが先に処理され、負の値を指定することもできます [https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_types]。
  +
  +
例えば、input パケットをフィルタリングするベースチェインを追加するには:
  +
  +
# nft add chain inet filter input { type filter hook input priority 0\; }
  +
  +
{{ic|add}} を {{ic|create}} に置き換えると、チェインが既に存在するときにエラーが返ってくるようになります。
  +
  +
==== ルールの表示 ====
  +
  +
以下のコマンドでチェインの全てのルールを表示できます:
  +
  +
# nft list chain ''family'' ''table'' ''chain''
  +
  +
例えば、{{ic|filter}} という名前の {{ic|inet}} テーブルに存在する {{ic|output}} という名前のチェインのルールを表示するには:
  +
  +
# nft list chain inet filter output
  +
  +
==== チェインの編集 ====
  +
  +
チェインを編集したいときは、チェインの名前を指定して変更したいルールを定義します:
  +
  +
# <nowiki>nft chain <table> <family> <chain> { [ type <type> hook <hook> device <device> priority <priority> \; policy <policy> \; ] }</nowiki>
  +
  +
例えば、デフォルトテーブルの input チェインポリシーを "accept" から "drop" に変更したい場合:
  +
  +
# nft chain inet filter input { policy drop \; }
  +
  +
==== チェインの削除 ====
  +
  +
チェインを削除するには:
  +
  +
# nft delete chain ''family'' ''table'' ''chain''
  +
  +
削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。
  +
  +
==== チェインのルールを消去 ====
  +
  +
チェインからルールを消去するには:
  +
  +
# nft flush chain ''family'' ''table'' ''chain''
   
===作成===
+
=== ルール ===
テーブルは2つのコマンド (片方はもう片方のショートカットです) で追加することができます。以下は foo という名前の ip テーブルと foo という名前の ip6 テーブルを追加する例です:
 
# nft add table foo
 
# nft table ip6 foo
 
ファミリーが異なっていれば同じ名前のテーブルを作ることが可能です。
 
   
  +
ルールは表現または宣言から構成され、チェインの中に格納されます。
===削除===
 
テーブルを削除することができるのはチェインが存在しない場合だけです。
 
# nft delete table foo
 
# nft delete table ip6 foo
 
   
  +
==== ルールの追加 ====
==チェイン==
 
チェインの用途はルールを保持することです。iptables のチェインと違って、nftables には初めから組み込まれているチェインはありません。そのためチェインが netfilter フレームワークにあるタイプやフックをどれも使わない場合、iptables とは異なりチェインを通り抜けるパケットは nftables の影響を受けません。
 
   
  +
{{Tip|''iptables-translate'' ユーティリティを使うことで [[iptables]] のルールを nftables フォーマットに変換できます。}}
===表示===
 
{{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}} テーブルに追加します。
 
   
  +
# nft add rule ''family'' ''table'' ''chain'' ''position'' ''statement''
====プロパティ====
 
nftables には組み込みチェインが存在しないため、チェインは netfilter フレームワークの特定の機能にアクセスすることができます。
 
# nft add chain filter input { type filter hook input priority 0\; }
 
上記コマンドは nftables に {{ic|input}} という名前のチェインを {{ic|filter}} テーブルに追加させ、そのタイプ・フック・プライオリティを定義します。これらのプロパティは基本的に iptables で組み込まれているテーブルやチェインを置き換えるものです。
 
   
  +
ルールは {{ic|''position''}} に追加されます。位置は指定しなくてもかまいません。指定しなかった場合、ルールはチェインの末尾に追加されます。
=====タイプ=====
 
チェインには3つのタイプがあり、iptables で使われているテーブルと対応しています:
 
*filter
 
*nat
 
*route (mangle)
 
   
  +
特定の位置の前にルールを追加するには:
=====フック=====
 
チェインは5つのフックを使うことができ、iptables で使われているチェインと対応しています:
 
*input
 
*output
 
*forward
 
*prerouting
 
*postrouting
 
   
  +
# nft insert rule ''family'' ''table'' ''chain'' ''position'' ''statement''
=====プライオリティ=====
 
{{Note|Priorities do not currently appear to have any effect on which chain sees packets first.}}
 
{{Note|Since the priority seems to be an unsigned integer, negative priorities will be converted into very high priorities.}}
 
プライオリティは nftables がどのパケットを初めに通過させるかを示します。整数で指定し、高い値を与えるほど優先されます。
 
   
  +
{{ic|''position''}} を指定しなかった場合、ルールはチェインの一番前に追加されます。
===削除===
 
チェインはルールが存在しない場合にのみ削除することができます。
 
# nft delete chain foo bar
 
# nft delete chain ip6 foo bar
 
以上のコマンドは ip と ip6 の {{ic|foo}} テーブルから {{ic|bar}} チェインを削除します。
 
   
==ルール==
+
===== 表現 =====
ルールの用途はパケットを識別(マッチ)して処理を実行(ジャンプ)することです。iptables と同じように、様々なマッチやジャンプが利用できますが、nftables には欠けている機能も存在します。
 
   
  +
{{ic|''statement''}} にはマッチする表現と判断宣言が入ります。判断宣言には {{ic|accept}}, {{ic|drop}}, {{ic|queue}}, {{ic|continue}}, {{ic|return}}, {{ic|jump ''chain''}}, {{ic|goto ''chain''}} などが存在します。判断宣言以外の宣言も指定できます。詳しくは {{man|8|nft}} を参照してください。
===表示===
 
テーブルを表示するのと同じ方法を使って、{{ic|nft list}} コマンドでテーブルの中の現在のルールを表示することができます。個別のチェインからルールを表示することも可能です。
 
# nft list chain foo bar
 
# nft list chain ip6 foo bar
 
These commands will list the rules in the {{ic|bar}} chains in the ip and ip6 {{ic|foo}} tables.
 
   
  +
nftables では様々な表現を使うことができ、ほとんどは、iptables と対応するようになっています。一番大きな違いは汎用的なマッチと暗黙的なマッチが存在しないことです。汎用的なマッチとは、{{ic|--protocol}} や {{ic|--source}} のように、いつでも使うことができるマッチで、暗黙的なマッチとは、{{ic|--sport}} のように、特定のプロトコルでしか使えないマッチのことです。
===作成===
 
テーブルがファイル定義や {{ic|nft add rule}} コマンドによって作成されたら、ルールを追加することができます。
 
# nft add rule foo bar ip saddr 127.0.0.1 accept
 
# nft add rule ip6 foo bar ip saddr ::1 accept
 
These commands will add a rule to the {{ic|bar}} chains in the ip and ip6 {{ic|foo}} tables that matches an {{ic|ip}} packet when its {{ic|saddr}} (source address) is 127.0.0.1 (IPv4) or ::1 (IPv6) and accepts those packets.
 
   
  +
以下は利用できるマッチの一部です:
====マッチ====
 
There are various matches available in nftables and, for the most part, coincide with their iptables counterparts. The most noticeable difference is that there are no generic or implicit matches anymore. A generic match was one that was always available, such as {{ic|--protocol}} or {{ic|--source}}. Implicit matches were protocol-specific, such as {{ic|--sport}} when a packet was determined to be TCP.
 
   
  +
* meta (メタプロパティ。例: インターフェイス)
The following is an incomplete list of the matches available:
 
  +
* icmp (ICMP プロトコル)
*meta (meta properties, e.g. interfaces)
 
  +
* icmpv6 (ICMPv6 プロトコル)
*icmp (ICMP protocol)
 
  +
* ip (IP プロトコル)
*icmpv6 (ICMPv6 protocol)
 
*ip (IP protocol)
+
* ip6 (IPv6 プロトコル)
*ip6 (IPv6 protocol)
+
* tcp (TCP プロトコル)
*tcp (TCP protocol)
+
* udp (UDP プロトコル)
*udp (UDP protocol)
+
* sctp (SCTP プロトコル)
  +
* ct (接続のトラッキング)
*sctp (SCTP protocol)
 
*ct (connection tracking)
 
   
  +
以下はマッチ引数の一部です (完全なリストは {{man|8|nft}} を見て下さい):
The following is an incomplete list of match arguments:
 
 
<nowiki>
 
<nowiki>
 
meta:
 
meta:
199行目: 267行目:
 
state <new | established | related | invalid></nowiki>
 
state <new | established | related | invalid></nowiki>
   
====ジャンプ====
+
====削除====
ジャンプ iptables と同じように使ことができますが、ひつのルールで複数ジャ使用できるようになっています。
+
個々のルールハンドルを使わないと削除することができません。{{ic|nft --handle list}} コマンドを使うこルールのドル確認できます。{{ic|--handle}} スイッチを付けると、{{ic|nft}} はハンドルを出力するようになます。
# nft add rule filter input tcp dport 22 log accept
 
   
  +
以下ではルールのハンドルを確認してルールを削除しています。未解決の IP アドレスのような、数字の出力を表示するときは {{ic|--number}} 引数を使うと良いでしょう。
以下はジャンプの未完成なリストです:
 
*accept (accept a packet)
 
*reject (reject a packet)
 
*drop (drop a packet)
 
*snat (perform source NAT on a packet)
 
*dnat (perform destination NAT on a packet)
 
*log (log a packet)
 
*counter (keep a counter on a packet; counters are optional in nftables)
 
*return (stop traversing the chain)
 
 
===挿入===
 
{{ic|nft insert rule}} コマンドでチェインにルールを挿入することができます。
 
# nft insert rule filter input ct state established,related accept
 
 
===削除===
 
Individual rules can only be deleted by their handles. The {{ic|nft --handle list}} command must be used to determine rule handles. Note the {{ic|--handle}} switch, which tells {{ic|nft}} to list handles in its output.
 
 
The following determines the handle for a rule and then deletes it. The {{ic|--number}} argument is useful for viewing some numeric output, like unresolved IP addresses.
 
 
{{hc|# nft --handle --numeric list chain filter input|2=
 
{{hc|# nft --handle --numeric list chain filter input|2=
 
<nowiki>
 
<nowiki>
table ip filter {
+
table ip fltrTable {
 
chain input {
 
chain input {
 
type filter hook input priority 0;
 
type filter hook input priority 0;
231行目: 281行目:
 
</nowiki>
 
</nowiki>
 
}}
 
}}
# nft delete rule filter input handle 10
+
# nft delete rule fltrTable input handle 10
   
All the chains in a table can be flushed with the {{ic|nft flush table}} command. Individual chains can be flushed using either the {{ic|nft flush chain}} or {{ic|nft delete rule}} commands.
+
{{ic|nft flush table}} コマンドを使うことでテーブルの全てのチェインをフラッシュできます。個別のチェインをフラッシュするときは {{ic|nft flush chain}} または {{ic|nft delete rule}} コマンドを使います。
 
# nft flush table foo
 
# nft flush table foo
 
# nft flush chain foo bar
 
# nft flush chain foo bar
 
# nft delete rule ip6 foo bar
 
# nft delete rule ip6 foo bar
  +
最初のコマンドでは ip {{ic|foo}} テーブルのチェイン全てをフラッシュします。2番目のコマンドは ip {{ic|foo}} テーブルの {{ic|bar}} チェインをフラッシュします。3番目のコマンドは ip6 {{ic|foo}} テーブルの {{ic|bar}} チェインの全てのルールを削除します。
The first command flushes all of the chains in the ip {{ic|foo}} table. The second flushes the {{ic|bar}} chain in the ip {{ic|foo}} table. The third deletes all of the rules in {{ic|bar}} chain in the ip6 {{ic|foo}} table.
 
   
  +
===アトミックリロード===
==ファイル定義==
 
  +
現在のルールセットをフラッシュする:
{{Warning|[http://people.netfilter.org/wiki-nftables/index.php/Atomic_rule_replacement netfilter wiki] に書かれていることとは違って、{{ic|nft -f}} コマンドは'''アトミックではありません'''。そのため古いテーブルを削除するのと新しいルールセットをロードする間に、全てのパケットを許可する必要があります。}}
 
  +
# echo "flush ruleset" > /tmp/nftables
{{Note|{{ic|nft -f}} コマンドは使う前に衝突するテーブルを全て削除する必要があります。}}
 
  +
現在のルールセットをダンプする:
{{ic|nft -f}} コマンドでファイル定義を利用することができます。このコマンドは {{ic|iptables-restore}} コマンドと同じように動作します。
 
  +
# nft list ruleset >> /tmp/nftables
{{hc|/etc/nftables/filter.rules|2=
 
  +
{{ic|/tmp/nftables}} を編集して次のコマンドで変更を適用:
<nowiki>
 
  +
# nft -f /tmp/nftables
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>
 
}}
 
   
==はじめに==
+
== サンプル ==
[[iptables|iptables]] のようなチェインを設定するには、まず備え付けの IPv4 フィルターファイルを使う必要があります:
 
   
  +
=== ワークステーション ===
# nft -f /etc/nftables/ipv4-filter
 
   
  +
{{hc|/etc/nftables.conf|2=<nowiki>
作成されたチェインを表示するには:
 
  +
flush ruleset
   
  +
table inet filter {
# nft list table filter
 
  +
chain input {
  +
type filter hook input priority 0;
   
  +
# accept any localhost traffic
Drop output to a destination:
 
  +
iif lo accept
   
  +
# accept traffic originated from us
# nft add rule ip filter output ip daddr 1.2.3.4 drop
 
  +
ct state established,related accept
   
  +
# activate the following line to accept common local services
Drop packets destined for local port 80:
 
  +
#tcp dport { 22, 80, 443 } ct state new accept
   
  +
# accept neighbour discovery otherwise IPv6 connectivity breaks.
# nft add rule ip filter input tcp dport 80 drop
 
  +
ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
   
  +
# count and drop any other traffic
Delete all rules in a chain:
 
  +
counter drop
  +
}
  +
}
  +
</nowiki>}}
   
  +
=== シンプルな IPv4/IPv6 ファイアウォール ===
# nft delete rule filter output
 
   
  +
{{hc|firewall.rules|2=<nowiki>
==サンプル==
 
===シンプルな IP/IPv6 ファイアウォール===
 
{{hc|firewall.rules|2=
 
<nowiki>
 
 
# A simple firewall
 
# A simple firewall
   
  +
flush ruleset
table firewall {
 
chain incoming {
 
type filter hook input priority 0;
 
   
  +
table inet filter {
# established/related connections
 
  +
chain input {
ct state {established, related} accept
 
  +
type filter hook input priority 0; policy drop;
   
# invalid connections
+
# established/related connections
ct state invalid drop
+
ct state established,related accept
   
  +
# invalid connections
# loopback interface
 
  +
ct state invalid drop
iifname lo accept
 
  +
  +
# loopback interface
  +
iif lo accept
   
  +
# ICMP
# icmp
 
  +
# routers may also want: mld-listener-query, nd-router-solicit
ip protocol icmp accept
 
  +
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)
# open tcp ports: sshd (22), httpd (80)
 
tcp dport {ssh, http} accept
+
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;
  +
}
   
# everything else
 
reject
 
}
 
 
}
 
}
  +
</nowiki>}}
   
  +
===レート制限 IPv4/IPv6 ファイアウォール===
table ip6 firewall {
 
chain incoming {
 
type filter hook input priority 0;
 
   
  +
{{hc|firewall.2.rules|2=<nowiki>
# established/related connections
 
  +
table inet filter {
ct state {established, related} accept
 
  +
chain input {
  +
type filter hook input priority 0; policy drop;
   
  +
# no ping floods:
# invalid connections
 
  +
ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 10/second accept
ct state invalid drop
 
  +
ip protocol icmp icmp type echo-request limit rate 10/second accept
   
  +
ct state established,related accept
# loopback interface
 
  +
ct state invalid drop
iifname lo accept
 
   
  +
iif lo accept
# icmp
 
ip6 nexthdr icmpv6 accept
 
   
  +
# avoid brute force on ssh:
# open tcp ports: sshd (22), httpd (80)
 
tcp dport {ssh, http} accept
+
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;
  +
}
   
# everything else
 
reject
 
}
 
 
}
 
}
</nowiki>
+
</nowiki>}}
}}
 
   
  +
===ジャンプ===
===Limit rate と tcp flags の IP/IPv6 ファイアウォール===
 
  +
{{hc|firewall.2.rules|2=
 
  +
設定ファイルでジャンプを使うときは、先にターゲットチェインを定義する必要があります。そうしないと {{ic|Error: Could not process rule: No such file or directory}} というエラーが発生します。
  +
{{hc|jump.rules|2=
 
<nowiki>
 
<nowiki>
table firewall {
+
table inet filter {
chain incoming {
+
chain web {
  +
tcp dport http accept
  +
tcp dport 8080 accept
  +
}
  +
chain input {
 
type filter hook input priority 0;
 
type filter hook input priority 0;
  +
ip saddr 10.0.2.0/24 jump web
  +
drop
  +
}
  +
}
  +
</nowiki>
  +
}}
   
  +
=== インターフェイスによってルールを変える ===
# bad tcp -> avoid network scanning:
 
tcp flags & (fin|syn) == (fin|syn) drop
 
tcp flags & (syn|rst) == (syn|rst) drop
 
tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) drop # == 0 would be better, not supported yet.
 
tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) drop
 
   
  +
複数のネットワークインターフェイスが存在する場合、それぞれのインターフェイスごとに別々のフィルターチェインを設定したい場合があるかもしれません。例えば、ホームルーターを構築するとき、LAN 上でアクセスできるウェブサーバーを実行しつつ ({{ic|nsp3s0}} インターフェイス)、インターネットからはアクセスできないようにしたい場合 ({{ic|enp2s0}} インターフェイス) などは以下のように設定します:
# no ping floods:
 
ip protocol icmp limit rate 10/second accept
 
ip protocol icmp drop
 
   
  +
<nowiki>table inet filter {
ct state {established, related} accept
 
  +
chain input { # this chain serves as a dispatcher
ct state invalid drop
 
  +
type filter hook input priority 0;
   
iifname lo accept
+
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
# avoid brute force on ssh:
 
  +
}
tcp dport {ssh} limit rate 15/minute accept
 
  +
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
  +
}
  +
}</nowiki>
   
  +
もしくは {{ic|iifname}} ステートメントを特定のインターフェイスで使用して、他のインターフェイスについてはデフォルトルールを設定するという方法もあります。
reject
 
}
 
}
 
   
  +
=== マスカレード ===
table ip6 firewall {
 
chain incoming {
 
type filter hook input priority 0;
 
   
  +
nftables には特殊なキーワード {{ic|masquerade}} が存在し、送信元アドレスが自動的に出力インターフェイスのアドレスに設定されます ([http://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_%28NAT%29#Masquerading ソース])。ルーターのインターフェイスが多数の ISP に接続されているときなど、インターフェイスの IP アドレスが一定でない場合に有用です。通常は、インターフェイスの IP アドレスが変わるたびにネットワークアドレス変換 (NAT) のルールを更新する必要があります。
# bad tcp:
 
tcp flags & (fin|syn) == (fin|syn) drop
 
tcp flags & (syn|rst) == (syn|rst) drop
 
tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) drop # == 0 would be better, not supported yet.
 
tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) drop
 
   
  +
{{ic|masquerade}} を使用するには:
# no ping floods:
 
ip6 nexthdr icmpv6 limit rate 10/second accept
 
ip6 nexthdr icmpv6 drop
 
   
  +
* カーネルコンフィグで以下のマスカレード設定が有効になっている必要があります。
ct state {established, related} accept
 
ct state invalid drop
 
   
  +
CONFIG_NFT_MASQ=m
# loopback interface
 
iifname lo accept
 
   
  +
* {{ic|masquerade}} キーワードは {{ic|nat}} タイプのチェインでのみ使うことができ、{{ic|inet}} ファミリーのテーブルでは利用できません。{{ic|ip}} ファミリーや {{ic|ip6}} ファミリーのテーブルを使ってください。
# avoid brute force on ssh:
 
  +
* マスカレードは一種のソース NAT であり、出力パスでのみ機能します。
tcp dport {ssh} limit rate 15/minute accept
 
   
  +
2つのインターフェイスが存在し {{ic|nsp3s0}} が LAN に接続され、{{ic|enp2s0}} がインターネットに接続されているマシンでの設定例:
reject
 
}
 
}
 
</nowiki>
 
}}
 
   
  +
<nowiki>table ip nat {
===Priority-based Atomic Fix===
 
  +
chain prerouting {
If priorities ever actually take effect, this may be a workaround for {{ic|nft -f}}'s lack of true atomicness (being able to replace all the current rules with new ones in one go):
 
  +
type nat hook prerouting priority 0;
{{hc|atomic.rules|2=
 
table atomic {
 
chain incoming {
 
type filter hook input priority 0;
 
ct state new reject
 
 
}
 
}
  +
chain postrouting {
}
 
  +
type nat hook postrouting priority 0;
 
  +
oifname "enp0s2" masquerade
table ip6 atomic {
 
chain incoming {
 
type filter hook input priority 0;
 
ct state new reject
 
 
}
 
}
  +
}</nowiki>
}
 
}}
 
Set the priority of other chains that hook input to higher than 0. This should block new connections while no other input chains are loaded.
 
   
  +
== ヒントとテクニック ==
===Rules Script with Atomic Fix===
 
Because using {{ic|nft -f}} to reload rulesets is time consuming, it's far easier to script it. This will include an atomic fix not based on priorities. It uses the two rules files from above.
 
{{hc|firewall.sh|2=
 
#!/bin/sh
 
   
  +
=== シンプルなステートフルファイアウォール ===
# Load atomic rules first
 
nft -f atomic.rules
 
   
  +
[[シンプルなステートフルファイアウォール]]の記事も参照してください。
# New incoming traffic should now be stopped
 
   
  +
==== シングルマシン ====
# Get rid of both the ip and ip6 firewall tables
 
   
  +
現在のルールセットを消去:
nft flush table firewall 2>/dev/null
 
nft delete chain firewall incoming 2>/dev/null
 
nft delete table firewall 2>/dev/null
 
   
nft flush table ip6 firewall 2>/dev/null
+
# nft flush ruleset
nft delete chain ip6 firewall incoming 2>/dev/null
 
nft delete table ip6 firewall 2>/dev/null
 
   
  +
テーブルを追加:
# Reload the firewall rules
 
nft -f firewall.rules
 
   
  +
# nft add table inet filter
# Get rid of both the ip and ip6 atomic tables
 
   
  +
input, forward, output ベースチェインを追加。input と forward のポリシーは破棄にして、output のポリシーは許可にする:
nft flush table atomic 2>/dev/null
 
nft delete chain atomic incoming 2>/dev/null
 
nft delete table atomic 2>/dev/null
 
   
  +
# nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
# New incoming IP traffic should be working
 
  +
# 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 flush table ip6 atomic 2>/dev/null
 
nft delete chain ip6 atomic incoming 2>/dev/null
 
nft delete table ip6 atomic 2>/dev/null
 
   
  +
# nft add chain inet filter TCP
# New incoming IPv6 traffic should be working
 
  +
# 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 と共に使う ===
  +
  +
{{Note|
  +
* 次のセットアップでは、{{ic|--net host --privileged}} を使用してもコンテナ内で {{ic|AF_BLUETOOTH}} などのプロトコルを利用できなくなります。
  +
* Rootless Dockerコンテナはすでに別のネットワーク名前空間で実行されています。何もする必要がないかもしれません。
 
}}
 
}}
This should take anywhere from 100ms to 400ms, which is clearly unacceptable, but the only apparent solution.
 
   
  +
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
  +
  +
# 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
システムの起動時にルールを自動的にロードするには、{{ic|systemctl enable nftables}} を実行して nftables の systemd サービスを有効にしてください。
 
   
  +
次に、[[インターネット共有#パケット転送の有効化|kernel IP forwarding]] が有効になっていることを確認します。
{{Note|systemd サービスが正しく動作するように必要な nftables 関連のモジュール全てのエントリを含む {{ic|/etc/modules-load.d/nftables.conf}} を作成する必要があります。モジュールのリストは次のコマンドで取得可能です: {{bc|<nowiki>lsmod | grep nf</nowiki>}} 作成していないと、{{ic|Error: Could not process rule: No such file or directory}} エラーで終了してしまいます。}}
 
   
==Syslog にログを出力する==
 
   
  +
これで、nftables を使用して {{ic|docker0}} インターフェイスのファイアウォールとポートフォワーディングを干渉することなくセットアップできるようになります。
Syslog にログを残すには、{{ic|xt_LOG}} モジュールをロードする必要があります。
 
   
 
==参照==
 
==参照==
* [http://people.netfilter.org/wiki-nftables/index.php/ netfilter nftables wiki]
+
* [https://wiki.nftables.org/ netfilter nftables wiki]
 
* [https://lwn.net/Articles/324251/ nftables の最初のリリース]
 
* [https://lwn.net/Articles/324251/ nftables の最初のリリース]
 
* [https://home.regit.org/netfilter-en/nftables-quick-howto/ nftables クイックハウツー]
 
* [https://home.regit.org/netfilter-en/nftables-quick-howto/ nftables クイックハウツー]
 
* [https://lwn.net/Articles/564095/ nftables の帰還]
 
* [https://lwn.net/Articles/564095/ nftables の帰還]
  +
* [https://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`]

2023年9月20日 (水) 15:51時点における最新版

関連記事

nftables は既存の ip-, ip6-, arp-, ebtables フレームワークを置き換える netfilter のプロジェクトです。新しいパケットフィルタリングフレームワーク、新しいユーザースペースユーティリティ (nft)、そして ip- と ip6tables の互換レイヤーを提供します。現行のフック、接続追跡システム、ユーザースペースのキューイングコンポーネント、そして netfilter のログサブシステムを使っています。

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

nftables の公式 wiki には詳しい情報が載っています。

インストール

nftables のユーザーランドユーティリティは nftables パッケージで利用できます。開発版の nftables-gitAUR パッケージも存在します。

ヒント: ほとんどの iptables フロントエンド はnftables の直接的または間接的なサポートを備えていませんが、導入することは可能です。[1] nftables と iptables の両方をサポートするグラフィカルなフロントエンドとしては、firewalld があります。[2]

使用方法

nftables ではコマンドラインで作成される一時的なルールと、ファイルに保存して読み込まれる永続的なルールを区別していません。デフォルトファイルの /etc/nftables.conf には "inet filter" という名前のシンプルな ipv4/ipv6 ファイアウォールテーブルが既に記述されています。

nftables.service起動有効化してください。

以下のコマンドでルールセットを確認できます:

# nft list ruleset

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

nftables には、/etc/nftables.conf ファイルに保存されたシンプルで安全なファイアウォール設定が付属しています。 ​ nftables.service は、起動または有効化時に、このファイルからルールを読み込みます。

設定

nftables のユーザースペースユーティリティ nft は現在カーネルのためにルールセットを処理する前にほとんどのルールセットの評価を行います。ルールはチェインに保存され、チェインはテーブルに保存されます。下のセクションではルールを作成・編集する方法を説明します。

下のセクションで行った変更は全て一時的なものになります。変更を永続化するにはルールセットを /etc/nftables.conf に保存してください (ルールセットは nftables.service によって読み込まれます):

# nft list ruleset > /etc/nftables.conf
ノート: nft list は変数の定義を出力しません。/etc/nftables.conf に何か記述していた場合、定義は失われます。ルールによって使われていた変数は変数の値に置き換えられます。

ファイルから入力するには -f フラグを使用します:

# nft -f 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 table

例えば inet ファミリーの filter テーブルのルールを全て表示するには:

# nft list table inet filter

テーブルの削除

テーブルを削除するには:

# nft delete table family table

テーブルはチェインが全く存在しない場合にのみ削除できます。

テーブルのクリア

テーブルから全てのルールを消去するには:

# nft flush table family table

チェイン

チェインの用途はルールを保持することです。iptables のチェインと違って、nftables には初めから組み込まれているチェインはありません。そのためチェインが netfilter フレームワークにあるタイプやフックをどれも使わない場合、iptables とは異なりチェインを通り抜けるパケットは nftables の影響を受けません。

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

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

チェインの作成

Regular チェイン

以下のコマンドは table という名前のテーブルに chain という名前のレギュラーチェインを追加します:

# nft add chain family table chain

例えば、inet アドレスファミリーの filter テーブルに tcpchain という名前のレギュラーチェインを追加するには:

# nft add chain inet filter tcpchain
Base チェイン

ベースチェインを追加するにはフックとプライオリティの値を指定します:

# nft add chain family table chain { type type hook hook priority priority \; }

typefilter, route, nat のどれかから選ぶことができます。

IPv4/IPv6/Inet アドレスファミリーでは hookprerouting, input, forward, output, postrouting のどれかになります。他のファミリーのフックについては nft(8) を参照してください。

priority には整数値を指定します。低い値のチェインが先に処理され、負の値を指定することもできます [3]

例えば、input パケットをフィルタリングするベースチェインを追加するには:

# nft add chain inet filter input { type filter hook input priority 0\; }

addcreate に置き換えると、チェインが既に存在するときにエラーが返ってくるようになります。

ルールの表示

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

# nft list chain family table chain

例えば、filter という名前の inet テーブルに存在する output という名前のチェインのルールを表示するには:

# nft list chain inet filter output

チェインの編集

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

# nft chain <table> <family> <chain> { [ type <type> hook <hook> device <device> priority <priority> \; policy <policy> \; ] }

例えば、デフォルトテーブルの input チェインポリシーを "accept" から "drop" に変更したい場合:

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

チェインの削除

チェインを削除するには:

# nft delete chain family table chain

削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。

チェインのルールを消去

チェインからルールを消去するには:

# nft flush chain family table chain

ルール

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

ルールの追加

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

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

# nft add rule family table chain position statement

ルールは position に追加されます。位置は指定しなくてもかまいません。指定しなかった場合、ルールはチェインの末尾に追加されます。

特定の位置の前にルールを追加するには:

# nft insert rule family table chain position statement

position を指定しなかった場合、ルールはチェインの一番前に追加されます。

表現

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>

削除

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

以下ではルールのハンドルを確認してルールを削除しています。未解決の IP アドレスのような、数字の出力を表示するときは --number 引数を使うと良いでしょう。

# nft --handle --numeric list chain filter input
table ip fltrTable {
     chain input {
          type filter hook input priority 0;
          ip saddr 127.0.0.1 accept # handle 10
     }
}
# nft delete rule fltrTable input handle 10

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

# nft flush table foo
# nft flush chain foo bar
# nft delete rule ip6 foo bar

最初のコマンドでは ip foo テーブルのチェイン全てをフラッシュします。2番目のコマンドは ip foo テーブルの bar チェインをフラッシュします。3番目のコマンドは ip6 foo テーブルの bar チェインの全てのルールを削除します。

アトミックリロード

現在のルールセットをフラッシュする:

# 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 タイプのチェインでのみ使うことができ、inet ファミリーのテーブルでは利用できません。ip ファミリーや ip6 ファミリーのテーブルを使ってください。
  • マスカレードは一種のソース NAT であり、出力パスでのみ機能します。

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

table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
  }
  chain postrouting {
    type nat hook postrouting priority 0;
    oifname "enp0s2" masquerade
  }
}

ヒントとテクニック

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

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

シングルマシン

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

# 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 などのプロトコルを利用できなくなります。
  • Rootless 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

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

参照