📛

Nftables覚書

2023/02/27に公開

概要

Linuxにおけるパケットフィルタリングやアドレス変換のバックエンドには以前よりiptablesが使用されてきました。nftablesはiptablesに変わる手段であり、現在のほとんどのディストリビューションでは、公式リポジトリからインストールすることができます。以下ではnftablesの動作についての内容をメモ程度にまとめたものです。

Nftablesとは

出典: https://storage.googleapis.com/zenn-user-upload/55d538788056-20230227.png
出典: https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks

上図はLinuxマシンでのパケットの流れを簡略化したものです。nftablesはNetfilterへ定義されたフックを使用します。フックとはパケットフィルタリングの際に判定を行うタイミングを指します。例えば、Input Hook はSSHサーバやWebサーバなどのアプリケーションへパケットが進入する直前で実行されるため、アプリケーションが実行する前に特定の送信元IPアドレスを持ったパケットを破棄するなどといったルール及びセット定義することができます。また、ルールはチェインごとに設定することができます。iptablesとは異なり、nftablesはチェインをあらかじめ定義することはありません。しかし、ベースチェインと呼ばれるチェインへエントリポイントとして、各フックを定義する必要があります。さらに、チェインはIPv4トラフィックごとやL2トラフィックごとといったテーブル(ファミリ) 単位で定義することができます。
用語をまとめると次のようになります。

  1. ルール: フィルタリングなどの処理
  2. フック: ルールを評価するタイミング
  3. チェイン: ルールのあつまり
  4. テーブル: フックを評価するレイヤやプロトコル

nftablesの起動

nftablesをインストールした直後はあらかじめ/etc/nftables.confへステートフルファイアウォールの設定が記述されています。この設定はsystemctl start nftables.servicenft -f /etc/nftables.confコマンドで実行することができます。ここで、留意する必要がある項目はnftablesは特定のデーモンを持たず、常にファイルからルールを読み込む点です。systemdExecStart行から確認することができます。

ステートフルファイアウォール

以下は/etc/nftables.confの内容です。

#!/usr/bin/nft -f
# vim:set ts=2 sw=2 et:

# IPv4/IPv6 Simple & Safe firewall ruleset.
# More examples in /usr/share/nftables/ and /usr/share/doc/nftables/examples/.

table inet filter
delete table inet filter
table inet filter {
  chain input {
    type filter hook input priority filter
    policy drop

    ct state invalid drop comment "early drop of invalid connections"
    ct state {established, related} accept comment "allow tracked connections"
    iifname lo accept comment "allow from loopback"
    ip protocol icmp accept comment "allow icmp"
    meta l4proto ipv6-icmp accept comment "allow icmp v6"
    tcp dport ssh accept comment "allow sshd"
    pkttype host limit rate 5/second counter reject with icmpx type admin-prohibited
    counter
  }
  chain forward {
    type filter hook forward priority filter
    policy drop
  }
}

table <ファミリ> <テーブル名>でテーブルを定義することができます。同様にchain <チェイン名>でチェインを定義することができます。ただし、ベースチェインにはフックと優先度を明記する必要があります。type <ベースチェインタイプ> hook <フック> priority <優先度>のように指定し、ベースチェインタイプはfilter, route, natの3つがあり、それぞれ使用できるフックやフックの処理内容が異なります。優先度は予約語か数値で指定することができます。

inetファミリにおけるフックの動作

nftablesをファイアウォールとして使用する際はほとんどの場合inetファミリが使用されます。inetファミリはIPv4とIPv6に関するパケットを扱います。

Prerouting

冒頭の図の通りNICに侵入したIPパケットが最初に処理されるHookです。この時点では宛先に関係なく処理することができます。

Input

Preroutingフック後に宛先がサーバのリスナーソケットなどのローカルプロセスの場合はInputフックへ進みます。このフックでは一般的なパケットフィルタリングをするファイアウォールとしての役割を定義することができます。

Output

ブラウザやWebサーバなどのローカルプロセスが生成するパケットは最初にOutputフックへ進みます。

Forward

Preroutingフック後に宛先が別のネットワークデバイスの場合はForwardフックへ進みます。ここでは転送するパケットに対しての処理が行われます。

Postrouting

NICから外部へ送信されるパケットはPostroutingフックへ進みます。このフックでは送信元アドレスを変換するNATとしての役割を定義することができます。

ルールの定義

nftablesのルールはチェイン内で定義することができ、ステートメントを含みます。
ステートメントとは前述でのacceptのようにパケットを許可、拒否、破棄するといったアクションやロギングの有効化といった操作を指定します。
式は使用することでインターフェース名やIPアドレス、ポート番号などを指定したルールを定義することができます。以下ではメタ式、IPv4ヘッダー式、TCPヘッダー式について説明します。式についてはここでは全てを説明しません。filterチェインでよく利用するものについて説明します。その他、必要な場合はmanページを参照してください。

メタ式

メタ式は次のように利用します。

meta <メタ式タイプ>

メタ式タイプは例えばiifnameやoifnameのように入出力のインターフェースを指定してパケットを評価することができます。

meta iifname “lo” accept

上記の場合、入力インターフェースがループバックのパケットを許可します。

IPv4ヘッダー式

IPv4ヘッダー式は次のように利用します。

ip <IPv4ヘッダー式タイプ>

IPv4ヘッダー式タイプへは、宛先IPアドレスや送信元IPアドレス、上位層のプロトコルなどを指定できます。

ip saddr 192.168.1.1/24 accept

上記の場合、送信元IPアドレスが192.168.1.1のパケットを許可します。

TCPヘッダー式

TCPヘッダー式は次のように利用します。

tcp <TCPヘッダー式タイプ>

TCPヘッダー式タイプへは、送信元ポート番号や宛先ポート番号などを指定することができます。

tcp dport 22 accept

上記の場合、宛先ポート番号が22のパケットを許可します。また、一部のウェルノウンポートについては予約語で指定することができます。tcp dport ssh acceptは上記と同じ意味です。

参考

Discussion