「Nftables」の版間の差分
Kusanaginoturugi (トーク | 投稿記録) (関連記事を修正) |
Kusanaginoturugi (トーク | 投稿記録) (→インストール: 英語版より転載) |
||
| 14行目: | 14行目: | ||
== インストール == |
== インストール == |
||
| − | + | nftables のユーザーランドユーティリティは {{Pkg|nftables}} パッケージで利用できます。開発版の {{AUR|nftables-git}} パッケージも存在します。 |
|
| + | |||
| + | {{Tip|Most [[iptables#Front-ends|iptables front-ends]] feature no direct or indirect support of nftables, but may introduce it.[https://www.spinics.net/lists/netfilter/msg58215.html] One graphical front-end that supports both, nftables and iptables, is [[firewalld]].[https://firewalld.org/2018/07/nftables-backend]}} |
||
== 使用方法 == |
== 使用方法 == |
||
2021年6月21日 (月) 17:54時点における版
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 パッケージも存在します。
使用方法
nftables ではコマンドラインで作成される一時的なルールと、ファイルに保存して読み込まれる永続的なルールを区別していません。デフォルトファイルの /etc/nftables.conf には "inet filter" という名前のシンプルな ipv4/ipv6 ファイアウォールテーブルが既に記述されています。
nftables.service を起動・有効化してください。
以下のコマンドでルールセットを確認できます:
# nft list ruleset
設定
nftables のユーザースペースユーティリティ nft は現在カーネルのためにルールセットを処理する前にほとんどのルールセットの評価を行います。ルールはチェインに保存され、チェインはテーブルに保存されます。下のセクションではルールを作成・編集する方法を説明します。
下のセクションで行った変更は全て一時的なものになります。変更を永続化するにはルールセットを /etc/nftables.conf に保存してください (ルールセットは nftables.service によって読み込まれます):
# nft list ruleset > /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 以上が必要で、ip と ip6 ファミリーを統一してルールを簡単に定義できます。
アドレスフファミリーの完全な定義は 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 \; }
type は filter, route, nat のどれかから選ぶことができます。
IPv4/IPv6/Inet アドレスファミリーでは hook は prerouting, input, forward, output, postrouting のどれかになります。他のファミリーのフックについては nft(8) を参照してください。
priority には整数値を指定します。低い値のチェインが先に処理され、負の値を指定することもできます [3]。
例えば、input パケットをフィルタリングするベースチェインを追加するには:
# nft add chain inet filter input { type filter hook input priority 0\; }
add を create に置き換えると、チェインが既に存在するときにエラーが返ってくるようになります。
ルールの表示
以下のコマンドでチェインの全てのルールを表示できます:
# 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
ルール
ルールは表現または宣言から構成され、チェインの中に格納されます。
ルールの追加
チェインにルールを追加するには:
# 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 を見てください。