「Nftables」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(同期)
(マークアップの訂正 (""使用しない"" -> '''使用しない''))
 
(8人の利用者による、間の16版が非表示)
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 のログサブシステムを使っています。
   
 
nftables は3つのメインコンポーネントから構成されています: カーネルの実装、libnl netlink communication そして nftables ユーザースペースフロントエンド。カーネルは netlink の設定インターフェイスだけでなく、小さなクラス言語インタプリタを使用するランタイムのルールセットの評価も提供します。libnl にはカーネルと通信するためのローレベルな関数が含まれています。nftables フロントエンドはユーザーが対話するものです。
 
nftables は3つのメインコンポーネントから構成されています: カーネルの実装、libnl netlink communication そして nftables ユーザースペースフロントエンド。カーネルは netlink の設定インターフェイスだけでなく、小さなクラス言語インタプリタを使用するランタイムのルールセットの評価も提供します。libnl にはカーネルと通信するためのローレベルな関数が含まれています。nftables フロントエンドはユーザーが対話するものです。
   
[http://wiki.nftables.org nftables の公式 wiki] には詳しい情報が載っています。
+
[https://wiki.nftables.org/wiki-nftables/index.php/Main_Page nftables の公式 wiki] には詳しい情報が載っています。
   
 
== インストール ==
 
== インストール ==
   
Linux カーネル 3.13 から nftables を使うことはできますが、できるかぎり最新のカーネルを使用すること推奨します。nftables のユーザーランドユーティリティは {{Pkg|nftables}} パッケージで利用できます。[[Arch User Repository|AUR]] には {{AUR|nftables-git}} パッケージも存在します。
+
nftables のユーザーランドユーティリティは {{Pkg|nftables}} パッケージで利用できます。開発版の {{AUR|nftables-git}} パッケージも存在します。
   
  +
{{Tip|ほとんどの [[iptables#Front-ends|iptables フロントエンド]] はnftables の直接的または間接的なサポートを備えていませんが、導入することは可能です。[https://www.spinics.net/lists/netfilter/msg58215.html] nftables と iptables の両方をサポートするグラフィカルなフロントエンドとしては、[[firewalld]] があります。[https://firewalld.org/2018/07/nftables-backend]}}
== 基本的な実装 ==
 
   
  +
== 使用方法 ==
他のファイアウォールと異なり、nftables ではコマンドラインで作成される一時的なルールと、ファイルに保存して読み込まれる永続的なルールを区別しています。デフォルトファイルの {{ic|/etc/nftables.conf}} には "inet filter" という名前のシンプルな ipv4/ipv6 ファイアウォールテーブルが既に記述されています。
 
   
  +
nftables ではコマンドラインで作成される一時的なルールと、ファイルに保存して読み込まれる永続的なルールを区別していません。デフォルトファイルの {{ic|/etc/nftables.conf}} には "inet filter" という名前のシンプルな ipv4/ipv6 ファイアウォールテーブルが既に記述されています。
=== デフォルトルールセットのロード ===
 
   
 
{{ic|nftables.service}} を[[起動]]・[[有効化]]してください。
 
{{ic|nftables.service}} を[[起動]]・[[有効化]]してください。
28行目: 28行目:
 
# nft list ruleset
 
# nft list ruleset
   
  +
=== シンプルなファイアウォール ===
inet filter テーブルの設定が表示された場合、デスクトップとしてインターネットを問題なく利用できます。
 
  +
  +
{{Pkg|nftables}} には、{{ic|/etc/nftables.conf}} ファイルに保存されたシンプルで安全なファイアウォール設定が付属しています。
  +
  +
{{ic|nftables.service}} は、[[起動]]または[[有効化]]時に、このファイルからルールを読み込みます。
   
  +
== 設定 ==
{{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}} エラーで終了してしまいます。}}
 
   
  +
nftables のユーザースペースユーティリティ {{ic|nft}} は現在カーネルのためにルールセットを処理する前にほとんどのルールセットの評価を行います。ルールはチェインに保存され、チェインはテーブルに保存されます。下のセクションではルールを作成・編集する方法を説明します。
== nft ==
 
nftables のユーザースペースユーティリティ {{ic|nft}} は現在カーネルのためにルールセットを処理する前にほとんどのルールセットの評価を行います。そのため、nftables はデフォルトのテーブルやチェインを提供していません。しかしながらユーザーが iptables のような設定をエミュレートすることが可能です。
 
   
  +
下のセクションで行った変更は全て一時的なものになります。変更を永続化するにはルールセットを {{ic|/etc/nftables.conf}} に保存してください (ルールセットは {{ic|nftables.service}} によって読み込まれます):
{{Note|{{Pkg|nftables}} には "filter" テーブルが記述されている {{ic|/etc/nftables.conf}} が含まれています。このテーブルのルールでは、特定のプロトコルだけを許可して、他のプロトコルは全て拒否するようになっています。}}
 
   
  +
# nft list ruleset > /etc/nftables.conf
nft は ifconfig や iproute2 と同じような感じで動作します。iptables のように引数のスイッチを使う代わりに、長く構造化された連続のコマンドになります。例えば:
 
nft add rule ip6 filter input ip6 saddr ::1 accept
 
{{ic|add}} はコマンドです。{{ic|rule}} は {{ic|add}} のサブコマンドです。{{ic|ip6}} は {{ic|rule}} の引数で、ip6 ファミリーを使うことを宣言しています。{{ic|filter}} と {{ic|input}} は {{ic|rule}} の引数で、それぞれ使用するテーブルとチェインを指定しています。残りはルールの定義で、マッチ ({{ic|ip}}) とパラメータ ({{ic|saddr}})、パラメータの引数 ({{ic|::1}}) そしてジャンプ ({{ic|accept}}) からなります。
 
   
  +
{{Note|{{ic|nft list}} は変数の定義を出力しません。{{ic|/etc/nftables.conf}} に何か記述していた場合、定義は失われます。ルールによって使われていた変数は変数の値に置き換えられます。}}
以下は nft で利用できるコマンドの不完全なリストです:
 
<nowiki>
 
list
 
tables [family]
 
table [family] <name>
 
chain [family] <table> <name>
 
   
  +
ファイルから入力するには {{ic|-f}} フラグを使用します:
add
 
table [family] <name>
 
chain [family] <table> <name> [chain definitions]
 
rule [family] <table> <chain> <rule definition>
 
   
  +
# nft -f ''filename''
table [family] <name> (shortcut for `add table`)
 
   
  +
ロード済みのルールは自動的に消去されることはないので注意してください。
insert
 
rule [family] <table> <chain> <rule definition>
 
   
  +
利用可能なコマンドの一覧は {{man|8|nft}} を参照してください。
delete
 
table [family] <name>
 
chain [family] <table> <name>
 
rule [family] <table> <handle>
 
   
  +
===テーブル===
flush
 
table [family] <name>
 
chain [family] <table> <name></nowiki>
 
{{ic|family}} は任意ですが、デフォルトは {{ic|ip}} になります。
 
   
  +
テーブルは[[#チェイン|チェイン]]を保持します。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルの数や名前はユーザーが自由に決めることができますが、各テーブルにはアドレスファミリーをひとつしか保持することができません。5つのファミリーのうち指定したファミリーのパケットにだけ適用されます:
==テーブル==
 
テーブルの用途はチェインを保持することです。iptables のテーブルと違って、nftables には初めから組み込まれているテーブルはありません。テーブルは指定の5つのファミリーのうちどれか一つを持つことができ、それによって様々な iptables のユーティリティを一つに統一します:
 
   
 
{| class="wikitable"
 
{| class="wikitable"
84行目: 69行目:
 
| bridge || ebtables
 
| bridge || ebtables
 
|}
 
|}
 
=== ファミリー ===
 
   
 
{{ic|ip}} (IPv4) がデフォルトのファミリーです。特に指定がなければ {{ic|ip}} が使われます。
 
{{ic|ip}} (IPv4) がデフォルトのファミリーです。特に指定がなければ {{ic|ip}} が使われます。
   
  +
IPv4 と IPv6 の両方に適用されるルールを作成するには {{ic|inet}} を使います。{{ic|inet}} を使うには Linux 3.15 以上が必要で、{{ic|ip}} と {{ic|ip6}} ファミリーを統一してルールを簡単に定義できます。
IPv6 は {{ic|ip6}} で指定できます。
 
  +
  +
{{Note|{{ic|inet}} は {{ic|nat}} タイプのチェインでは使えず、{{ic|filter}} タイプのチェインを使う必要があります ([https://www.spinics.net/lists/netfilter/msg56411.html ソース])。}}
  +
  +
アドレスフファミリーの完全な定義は {{man|8|nft}} の {{ic|ADDRESS FAMILIES}} セクションを参照してください。
  +
  +
以下で例示しているコマンドの {{ic|''family''}} は全て任意であり、指定しなかった場合は {{ic|ip}} が使われます。
  +
  +
==== テーブルの作成 ====
  +
  +
以下のコマンドで新しいテーブルが追加されます:
  +
  +
# nft add table ''family'' ''table''
   
  +
==== テーブルの表示 ====
IPv4 と IPv6 の両方に適用されるルールを作成するには {{ic|inet}} を使います。Linux 3.15 以上が必要で、{{ic|ip}} と {{ic|ip6}} ファミリーを統一してルールを簡単に定義できます。
 
   
  +
全てのテーブルを表示するには:
{{Note|{{ic|inet}} は {{ic|nat}} タイプのチェインでは使えず、{{ic|filter}} タイプのチェインを使う必要があります ([http://www.spinics.net/lists/netfilter/msg56411.html ソース])。}}
 
   
===表示===
 
ファミリーの現在のテーブルは {{ic|nft list}} コマンドで一覧できます。
 
 
# nft list tables
 
# nft list tables
# nft list tables ip6
 
   
テーブルの名前を指定するこで完全なテルの定義を一覧できます:
+
==== テーブルチェインールの表示 ====
# nft list table ''foo''
 
# nft list table ''ip6 foo''
 
   
  +
指定したテーブルの全てのチェインとルールを表示するには:
===作成===
 
テーブルは2つのコマンド (片方はもう片方のショートカットです) で追加することができます。以下は foo という名前の ip テーブルと foo という名前の ip6 テーブルを追加する例です:
 
# nft add table ''foo''
 
# nft table ''ip6 foo''
 
ファミリーが異なっていれば同じ名前のテーブルを作ることが可能です。
 
   
  +
# nft list table ''family'' ''table''
===削除===
 
テーブルを削除することができるのはチェインが存在しない場合だけです。
 
# nft delete table ''foo''
 
# nft delete table ''ip6 foo''
 
   
  +
例えば {{ic|inet}} ファミリーの {{ic|filter}} テーブルのルールを全て表示するには:
==チェイン==
 
チェインの用途はルールを保持することです。iptables のチェインと違って、nftables には初めから組み込まれているチェインはありません。そのためチェインが netfilter フレームワークにあるタイプやフックをどれも使わない場合、iptables とは異なりチェインを通り抜けるパケットは nftables の影響を受けません。
 
   
  +
# nft list table inet filter
===表示===
 
{{ic|nft list table foo}} コマンドは foo テーブルの全てのチェインを表示します。個々のチェインからルールを一覧することもできます。
 
# nft list chain ''foo'' ''bar''
 
# nft list chain ''ip6 foo bar''
 
上記コマンドは ip と ip6 の {{ic|foo}} テーブルの {{ic|bar}} チェインを表示します。
 
   
  +
==== テーブルの削除 ====
===作成===
 
テーブルがファイル定義や {{ic|nft add chain}} コマンドによって作成されたら、チェインを追加することができます。
 
# nft add chain ''foo'' ''bar''
 
# nft add chain ''ip6 foo bar''
 
上記コマンドは {{ic|bar}} という名前のチェインを ip と ip6 の {{ic|foo}} テーブルに追加します。
 
   
  +
テーブルを削除するには:
====プロパティ====
 
nftables には組み込みチェインが存在しないため、チェインは netfilter フレームワークの特定の機能にアクセスすることができます。
 
# nft add chain filter input \{ type filter hook input priority 0\; \}
 
上記コマンドは nftables に {{ic|input}} という名前のチェインを {{ic|filter}} テーブルに追加させ、そのタイプ・フック・プライオリティを定義します。これらのプロパティは基本的に iptables で組み込まれているテーブルやチェインを置き換えるものです。
 
   
  +
# nft delete table ''family'' ''table''
=====タイプ=====
 
チェインには3つのタイプがあり、iptables で使われているテーブルと対応しています:
 
*filter
 
*nat
 
*route (mangle)
 
   
  +
テーブルはチェインが全く存在しない場合にのみ削除できます。
=====フック=====
 
チェインは6つのフックを使うことができ、ingress 以外は iptables で使われているチェインと対応しています:
 
*ingress
 
*input
 
*output
 
*forward
 
*prerouting
 
*postrouting
 
   
  +
==== テーブルのクリア ====
ingress フックは既存の {{ic|tc}} ユーティリティを置き換えます。
 
   
  +
テーブルから全てのルールを消去するには:
=====プライオリティ=====
 
{{Note|
 
* パケットが先に来るチェインにはプライオリティの効果はありません。
 
* プライオリティは符号なしの整数として設定するようになっているため、負のプライオリティを設定した場合、優先度は逆に高くなります。}}
 
プライオリティは nftables がどのパケットを初めに通過させるかを示します。整数で指定し、高い値を与えるほど優先されます。
 
   
  +
# 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>
 
# <nowiki>nft chain <table> <family> <chain> { [ type <type> hook <hook> device <device> priority <priority> \; policy <policy> \; ] }</nowiki>
   
例えば、デフォルトテーブルの input チェインポリシーを "accept" から "drop" に変更するには:
+
例えば、デフォルトテーブルの input チェインポリシーを "accept" から "drop" に変更したい場合:
   
 
# nft chain inet filter input { policy drop \; }
 
# nft chain inet filter input { policy drop \; }
   
===削除===
+
==== チェインの削除 ====
  +
チェインはルールが存在しない場合にのみ削除することができます。
 
  +
チェインを削除するには:
# nft delete chain ''foo bar''
 
  +
# nft delete chain ''ip6 foo bar''
 
  +
# nft delete chain ''family'' ''table'' ''chain''
以上のコマンドは ip と ip6 の {{ic|foo}} テーブルから {{ic|bar}} チェインを削除します。
 
  +
  +
削除するチェインにはルールやジャンプターゲットが含まれていてはいけません。
  +
  +
==== チェインのルールを消去 ====
  +
  +
チェインからルールを消去するには:
  +
  +
# nft flush chain ''family'' ''table'' ''chain''
  +
  +
=== ルール ===
  +
  +
ルールは表現または宣言から構成され、チェインの中に格納されます。
  +
  +
==== ルールの追加 ====
  +
  +
{{Tip|''iptables-translate'' ユーティリティを使うことで [[iptables]] のルールを nftables フォーマットに変換できます。}}
  +
  +
チェインにルールを追加するには:
  +
  +
# nft add rule ''family'' ''table'' ''chain'' ''position'' ''statement''
  +
  +
ルールは {{ic|''position''}} に追加されます。位置は指定しなくてもかまいません。指定しなかった場合、ルールはチェインの末尾に追加されます。
  +
  +
特定の位置の前にルールを追加するには:
  +
  +
# nft insert rule ''family'' ''table'' ''chain'' ''position'' ''statement''
   
  +
{{ic|''position''}} を指定しなかった場合、ルールはチェインの一番前に追加されます。
==ルール==
 
ルールの用途はパケットを識別(マッチ)して処理を実行(ジャンプ)することです。iptables と同じように、様々なマッチやジャンプが利用できますが、nftables には欠けている機能も存在します。
 
   
===表===
+
===== 現 =====
テーブルを表示するのと同じ方法を使って、{{ic|nft list}} コマンドでテーブルの中の現在のルールを表示することができます。個別のチェインからルールを表示することも可能です。
 
# nft list chain ''foo bar''
 
# nft list chain ''ip6 foo bar''
 
上記のコマンドで、ip と ip6 の {{ic|foo}} テーブルの {{ic|bar}} チェインのルールが表示されます。
 
   
  +
{{ic|''statement''}} にはマッチする表現と判断宣言が入ります。判断宣言には {{ic|accept}}, {{ic|drop}}, {{ic|queue}}, {{ic|continue}}, {{ic|return}}, {{ic|jump ''chain''}}, {{ic|goto ''chain''}} などが存在します。判断宣言以外の宣言も指定できます。詳しくは {{man|8|nft}} を参照してください。
===作成===
 
テーブルがファイル定義や {{ic|nft add rule}} コマンドによって作成されたら、ルールを追加することができます。
 
# nft add rule foo bar ip saddr 127.0.0.1 accept
 
# nft add rule ip6 foo bar ip saddr ::1 accept
 
上記のコマンドで、ip と ip6 の {{ic|foo}} テーブルの {{ic|bar}} チェインにルールが追加され、{{ic|saddr}} (ソースアドレス) が 127.0.0.1 (IPv4) や ::1 (IPv6) の場合に {{ic|ip}} パケットにマッチして、パケットを許可します。
 
   
  +
nftables では様々な表現を使うことができ、ほとんどは、iptables と対応するようになっています。一番大きな違いは汎用的なマッチと暗黙的なマッチが存在しないことです。汎用的なマッチとは、{{ic|--protocol}} や {{ic|--source}} のように、いつでも使うことができるマッチで、暗黙的なマッチとは、{{ic|--sport}} のように、特定のプロトコルでしか使えないマッチのことです。
====マッチ====
 
nftables では様々なマッチを使うことができ、ほとんどは、iptables と対応するようになっています。一番大きな違いは汎用的なマッチと暗黙的なマッチが存在しないことです。汎用的なマッチとは、{{ic|--protocol}} や {{ic|--source}} のように、いつでも使うことができるマッチで、暗黙的なマッチとは、{{ic|--sport}} のように、特定のプロトコルでしか使えないマッチのことです。
 
   
 
以下は利用できるマッチの一部です:
 
以下は利用できるマッチの一部です:
204行目: 226行目:
 
* ct (接続のトラッキング)
 
* ct (接続のトラッキング)
   
以下はマッチ引数の一部です (完全なリストは {{man|8|nft|url=http://www.netfilter.org/projects/nftables/manpage.html}} を見て下さい):
+
以下はマッチ引数の一部です (完全なリストは {{man|8|nft}} を見て下さい):
 
<nowiki>
 
<nowiki>
 
meta:
 
meta:
245行目: 267行目:
 
state <new | established | related | invalid></nowiki>
 
state <new | established | related | invalid></nowiki>
   
====ジャンプ====
+
====削除====
ジャンプは iptables と同じように使うことができますが、ひとつのルールで複数のジャンプを使用できるようになっています。
 
# nft add rule filter input tcp dport 22 log accept
 
 
以下はジャンプの未完成なリストです:
 
*accept (accept a packet)
 
*reject (reject a packet)
 
*drop (drop a packet)
 
*snat (perform source NAT on a packet)
 
*dnat (perform destination NAT on a packet)
 
*log (log a packet)
 
*counter (keep a counter on a packet; counters are optional in nftables)
 
*return (stop traversing the chain)
 
*jump <chain> (jump to another chain)
 
*goto <chain> (jump to another chain, but do not return)
 
 
===挿入===
 
 
====先頭に追加====
 
{{ic|nft insert rule}} コマンドでチェインにルールを挿入することができます。
 
# nft insert rule filter input ct state established,related accept
 
 
==== 特定の場所に追加 ====
 
 
Nftables はハンドルを使用してルールの位置を定義します。情報を取得するには、-a フラグを付けてルールセットを確認してください:
 
 
# nft list ruleset -a
 
 
特定のハンドラが付いているルールの後にルールを追加するには:
 
 
# nft add rule ''table_name'' ''chain_name'' position ''handler_number'' ''[rule-definition]''
 
 
===削除===
 
 
個々のルールはハンドルを使わないと削除することができません。{{ic|nft --handle list}} コマンドを使うことでルールのハンドルを確認できます。{{ic|--handle}} スイッチを付けると、{{ic|nft}} はハンドルを出力するようになります。
 
個々のルールはハンドルを使わないと削除することができません。{{ic|nft --handle list}} コマンドを使うことでルールのハンドルを確認できます。{{ic|--handle}} スイッチを付けると、{{ic|nft}} はハンドルを出力するようになります。
   
307行目: 297行目:
 
# nft -f /tmp/nftables
 
# nft -f /tmp/nftables
   
==ファイ定義==
+
== サンプ ==
{{ic|nft -f}} コマンドでファイル定義を利用することができます。このコマンドは {{ic|iptables-restore}} コマンドと同じように動作します。ただし、{{ic|iptables-restore}} と違って、既存のルールセットをフラッシュしないので、前もって flush コマンドを実行する必要があります。
 
{{hc|/etc/nftables/filter.rules|2=
 
<nowiki>
 
flush table ip filter
 
table ip filter {
 
chain input {
 
type filter hook input priority 0;
 
ct state established,related accept
 
ip saddr 127.0.0.1 accept
 
tcp dport 22 log accept
 
reject
 
}
 
}
 
</nowiki>
 
}}
 
   
  +
=== ワークステーション ===
ルールを ({{ic|iptables-save}} のように) エクスポートするには:
 
# nft list ruleset
 
   
  +
{{hc|/etc/nftables.conf|2=<nowiki>
==基本的なファイアウォール==
 
  +
flush ruleset
以下の例は ''nft'' コマンドを使ってベーシックな ''IPv4'' ファイアウォールを設定する方法を示しています。IPv4 と IPv6 の両方をフィルタリングしたい場合、{{ic|/usr/share/nftables}} にある他のサンプルを見たり、{{ic|/etc/nftables.conf}} のデフォルト (IPv4/IPv6 で動作するように設定済みです) を使うようにしてください。
 
   
  +
table inet filter {
[[iptables]] のようなチェインを設定するには、まず備え付けの IPv4 フィルターファイルを使う必要があります:
 
  +
chain input {
  +
type filter hook input priority 0;
   
  +
# accept any localhost traffic
# nft -f /usr/share/nftables/ipv4-filter
 
  +
iif lo accept
   
  +
# accept traffic originated from us
作成されたチェインを表示するには:
 
  +
ct state established,related accept
   
  +
# activate the following line to accept common local services
# nft list table filter
 
  +
#tcp dport { 22, 80, 443 } ct state new accept
   
  +
# accept neighbour discovery otherwise IPv6 connectivity breaks.
Drop output to a destination:
 
  +
ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
   
  +
# count and drop any other traffic
# nft add rule ip filter output ip daddr 1.2.3.4 drop
 
  +
counter drop
 
  +
}
Drop packets destined for local port 80:
 
  +
}
 
  +
</nowiki>}}
# nft add rule ip filter input tcp dport 80 drop
 
 
チェインの全てのルールを削除:
 
 
# nft delete rule filter output
 
   
==ンプル==
+
=== シンプルな IPv4/IPv6 ファイアウォール ===
===シンプルな IP/IPv6 ファイアウォール===
 
   
 
{{hc|firewall.rules|2=<nowiki>
 
{{hc|firewall.rules|2=<nowiki>
379行目: 354行目:
 
tcp dport ssh accept
 
tcp dport ssh accept
   
# HTTP (ports 80 & 445)
+
# HTTP (ports 80 & 443)
 
tcp dport { http, https } accept
 
tcp dport { http, https } accept
 
}
 
}
}</nowiki>}}
 
   
  +
chain forward {
===Limit rate IP/IPv6 ファイアウォール===
 
  +
type filter hook forward priority 0; policy drop;
  +
}
  +
  +
chain output {
  +
type filter hook output priority 0; policy accept;
  +
}
  +
  +
}
  +
</nowiki>}}
  +
  +
===レート制限 IPv4/IPv6 ファイアウォール===
   
 
{{hc|firewall.2.rules|2=<nowiki>
 
{{hc|firewall.2.rules|2=<nowiki>
398行目: 383行目:
 
ct state invalid drop
 
ct state invalid drop
   
iifname lo accept
+
iif lo accept
   
 
# avoid brute force on ssh:
 
# avoid brute force on ssh:
404行目: 389行目:
   
 
}
 
}
  +
  +
chain forward {
  +
type filter hook forward priority 0; policy drop;
  +
}
  +
  +
chain output {
  +
type filter hook output priority 0; policy accept;
  +
}
  +
 
}
 
}
 
</nowiki>}}
 
</nowiki>}}
   
 
===ジャンプ===
 
===ジャンプ===
  +
 
設定ファイルでジャンプを使うときは、先にターゲットチェインを定義する必要があります。そうしないと {{ic|Error: Could not process rule: No such file or directory}} というエラーが発生します。
 
設定ファイルでジャンプを使うときは、先にターゲットチェインを定義する必要があります。そうしないと {{ic|Error: Could not process rule: No such file or directory}} というエラーが発生します。
 
{{hc|jump.rules|2=
 
{{hc|jump.rules|2=
424行目: 419行目:
 
</nowiki>
 
</nowiki>
 
}}
 
}}
 
== 実践的なサンプル ==
 
   
 
=== インターフェイスによってルールを変える ===
 
=== インターフェイスによってルールを変える ===
435行目: 428行目:
 
type filter hook input priority 0;
 
type filter hook input priority 0;
   
iifname lo accept # always accept loopback
+
iif lo accept # always accept loopback
 
iifname enp2s0 jump input_enp2s0
 
iifname enp2s0 jump input_enp2s0
 
iifname enp3s0 jump input_enp3s0
 
iifname enp3s0 jump input_enp3s0
471行目: 464行目:
 
{{ic|masquerade}} を使用するには:
 
{{ic|masquerade}} を使用するには:
   
* カーネルのバージョンが 3.18 以上である必要があります。
 
 
* カーネルコンフィグで以下のマスカレード設定が有効になっている必要があります。
 
* カーネルコンフィグで以下のマスカレード設定が有効になっている必要があります。
   
491行目: 483行目:
 
}</nowiki>
 
}</nowiki>
   
  +
== ヒントとテクニック ==
==Syslog にログを出力する==
 
  +
  +
=== シンプルなステートフルファイアウォール ===
  +
  +
[[シンプルなステートフルファイアウォール]]の記事も参照してください。
  +
  +
==== シングルマシン ====
  +
  +
現在のルールセットを消去:
  +
  +
# 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 と共に使う ===
  +
  +
{{Note|
  +
* 次のセットアップでは、{{ic|--net host --privileged}} を使用してもコンテナ内で {{ic|AF_BLUETOOTH}} などのプロトコルを利用できなくなります。
  +
* Rootless Dockerコンテナはすでに別のネットワーク名前空間で実行されています。何もする必要がないかもしれません。
  +
}}
  +
  +
nftables を使用すると、[[Docker]] のネットワーク (おそらく他のコンテナランタイムも同様) に干渉する可能性があります。
  +
iptables ルールにパッチを適用して定義されたサービス開始順序を確保するか、docker の使用が非常に制限される dockerのiptablesの管理を完全に無効にするなど、さまざまな回避策がインターネット上で見つかります。
  +
(ポートフォワーディングや docker-compose を考えてください)
  +
  +
信頼できる方法は、docker を別のネットワーク名前空間で実行させ、そこで任意の処理を実行できるようにすることです。
  +
Docker が nftables と iptables ルールを混在させないように、{{Pkg|iptables-nft}} を'''使用しない'''方が良いでしょう。
  +
  +
以下の docker サービス [[ドロップインファイル]] を使用してください:
  +
  +
{{hc|/etc/systemd/system/docker.service.d/netns.conf|2=
  +
[Service]
  +
PrivateNetwork=yes
  +
  +
# cleanup
  +
ExecStartPre=-nsenter -t 1 -n -- ip link delete docker0
  +
  +
# add veth
  +
ExecStartPre=nsenter -t 1 -n -- ip link add docker0 type veth peer name docker0_ns
  +
ExecStartPre=sh -c 'nsenter -t 1 -n -- ip link set docker0_ns netns "$$BASHPID" && true'
  +
ExecStartPre=ip link set docker0_ns name eth0
  +
  +
# bring host online
  +
ExecStartPre=nsenter -t 1 -n -- ip addr add 10.0.0.1/24 dev docker0
  +
ExecStartPre=nsenter -t 1 -n -- ip link set docker0 up
  +
  +
# bring ns online
  +
ExecStartPre=ip addr add 10.0.0.100/24 dev eth0
  +
ExecStartPre=ip link set eth0 up
  +
ExecStartPre=ip route add default via 10.0.0.1 dev eth0
  +
}}
  +
  +
セットアップにおいてIPアドレス {{ic|10.0.0.*}} が適切でない場合は、調整してください。
  +
  +
以下のポストルーティングルールで、{{ic|docker0}} のIPフォワーディングを有効にし、NATを設定します:
  +
  +
iifname docker0 oifname eth0 masquerade
  +
  +
次に、[[インターネット共有#パケット転送の有効化|kernel IP forwarding]] が有効になっていることを確認します。
  +
   
  +
これで、nftables を使用して {{ic|docker0}} インターフェイスのファイアウォールとポートフォワーディングを干渉することなくセットアップできるようになります。
Linux カーネル 3.17 未満を使っている場合、ログ出力を有効にするには {{ic|xt_LOG}} を modprobe する必要があります。
 
   
 
==参照==
 
==参照==
500行目: 619行目:
 
* [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 の帰還]
* [http://developers.redhat.com/blog/2016/10/28/what-comes-after-iptables-its-successor-of-course-nftables/ What comes after ‘iptables’? It’s successor, of course: `nftables`]
+
* [https://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 インターフェイスのファイアウォールとポートフォワーディングを干渉することなくセットアップできるようになります。

参照