Red Hat Training

A Red Hat training course is available for RHEL 8

21.6. nftables の使用

nftables フレームワークはパケットを分類し、iptablesip6tablesarptablesebtables、および ipset ユーティリティーの後継です。利便性、機能、パフォーマンスにおいて、以前のパケットフィルタリングツールに多くの改良が追加されました。以下に例を示します。

  • 線形処理の代わりに組み込みルックアップテーブルを使用
  • IPv4 プロトコルおよび IPv6 プロトコルに対する 1 つのフレームワーク
  • 完全ルールセットのフェッチ、更新、および保存を行わず、すべてアトミックに適用されるルール
  • ルールセットにおけるデバッグおよびトレースへの対応 (nftrace) およびトレースイベントの監視 (nft ツール)
  • より統一されたコンパクトな構文、プロトコル固有の拡張なし
  • サードパーティーのアプリケーション用 Netlink API

nftables フレームワークは、テーブルを使用してチェーンを保存します。このチェーンには、アクションを実行する個々のルールが含まれます。nft ユーティリティーは、以前のパケットフィルタリングフレームワークのツールをすべて置き換えます。libmnl ライブラリーを介して、nftables Netlink API との低レベルの対話に libnftnl ライブラリーを使用できます。

ルールセット変更が適用されていることを表示するには、nft list ruleset コマンドを使用します。これらのユーティリティーはテーブル、チェーン、ルール、セット、およびその他のオブジェクトを nftables ルールセットに追加するため、nft flush ruleset コマンドなどの nftables ルールセット操作は、iptables コマンドを使用してインストールされたルールセットに影響を与える可能性があることに注意してください。

21.6.1. iptables から nftables への移行

ファイアウォール設定が依然として iptables ルールを使用している場合は、iptables ルールを nftables に移行できます。

21.6.1.1. firewalld、nftables、または iptables を使用する場合

以下は、次のユーティリティーのいずれかを使用する必要があるシナリオの概要です。

  • firewalld:簡単なファイアウォールのユースケースには、firewalld ユーティリティーを使用します。このユーティリティーは、使いやすく、このようなシナリオの一般的な使用例に対応しています。
  • nftables:nftables ユーティリティーを使用して、ネットワーク全体など、複雑なパフォーマンスに関する重要なファイアウォールを設定します。
  • iptables:Red Hat Enterprise Linux の iptables ユーティリティーは、legacy バックエンドの代わりに nf_tables カーネル API を使用します。nf_tables API は、iptables コマンドを使用するスクリプトが、Red Hat Enterprise Linux で引き続き動作するように、後方互換性を提供します。新しいファイアウォールスクリプトの場合には、Red Hat は nftables を使用することを推奨します。
重要

ファイアウォールサービスがそれぞれに影響し合うことを回避するためには、RHEL ホストでそのうちの 1 つだけを実行し、他のサービスを無効にします。

21.6.1.2. iptables および ip6tables ルールセットの nftables への変換

iptables-restore-translate ユーティリティーおよび ip6tables-restore-translate ユーティリティーを使用して、iptables および ip6tables ルールセットを nftables に変換します。

前提条件

  • nftables パッケージおよび iptables パッケージがインストールされている。
  • システムに iptables ルールおよび ip6tables ルールが設定されている。

手順

  1. iptables ルールおよび ip6tables ルールをファイルに書き込みます。

    # iptables-save >/root/iptables.dump
    # ip6tables-save >/root/ip6tables.dump
  2. ダンプファイルを nftables 命令に変換します。

    # iptables-restore-translate -f /root/iptables.dump > /etc/nftables/ruleset-migrated-from-iptables.nft
    # ip6tables-restore-translate -f /root/ip6tables.dump > /etc/nftables/ruleset-migrated-from-ip6tables.nft
  3. 必要に応じて、生成された nftables ルールを手動で更新して、確認します。
  4. nftables サービスが生成されたファイルをロードできるようにするには、以下を /etc/sysconfig/nftables.conf ファイルに追加します。

    include "/etc/nftables/ruleset-migrated-from-iptables.nft"
    include "/etc/nftables/ruleset-migrated-from-ip6tables.nft"
  5. iptables サービスを停止し、無効にします。

    # systemctl disable --now iptables

    カスタムスクリプトを使用して iptables ルールを読み込んだ場合は、スクリプトが自動的に開始されなくなったことを確認し、再起動してすべてのテーブルをフラッシュします。

  6. nftables サービスを有効にして起動します。

    # systemctl enable --now nftables

検証

  • nftables ルールセットを表示します。

    # nft list ruleset

21.6.1.3. 単一の iptables および ip6tables ルールセットの nftables への変換

Red Hat Enterprise Linux は、iptables ルールまたは ip6tables ルールを、nftables で同等のルールに変換する iptables-translate ユーティリティーおよび ip6tables-translate ユーティリティーを提供します。

前提条件

  • nftables パッケージがインストールされている。

手順

  • 以下のように、iptables または ip6tables の代わりに iptables-translate ユーティリティーまたは ip6tables-translate ユーティリティーを使用して、対応する nftables ルールを表示します。

    # iptables-translate -A INPUT -s 192.0.2.0/24 -j ACCEPT
    nft add rule ip filter INPUT ip saddr 192.0.2.0/24 counter accept

    拡張機能によっては変換機能がない場合もあります。このような場合には、ユーティリティーは、以下のように、前に # 記号が付いた未変換ルールを出力します。

    # iptables-translate -A INPUT -j CHECKSUM --checksum-fill
    nft # -A INPUT -j CHECKSUM --checksum-fill

関連情報

  • iptables-translate --help

21.6.1.4. 一般的な iptables コマンドと nftables コマンドの比較

以下は、一般的な iptables コマンドと nftables コマンドの比較です。

  • すべてのルールをリスト表示します。

    iptablesnftables

    iptables-save

    nft list ruleset

  • 特定のテーブルおよびチェーンをリスト表示します。

    iptablesnftables

    iptables -L

    nft list table ip filter

    iptables -L INPUT

    nft list chain ip filter INPUT

    iptables -t nat -L PREROUTING

    nft list chain ip nat PREROUTING

    nft コマンドは、テーブルおよびチェーンを事前に作成しません。これらは、ユーザーが手動で作成した場合にのみ存在します。

    firewalld によって生成されたルールの一覧表示:

    # nft list table inet firewalld
    # nft list table ip firewalld
    # nft list table ip6 firewalld

21.6.1.5. 関連情報

21.6.2. nftables スクリプトの作成および実行

nftables` フレームワークを使用する主な利点は、スクリプトの実行がアトミックであることです。つまり、システムがスクリプト全体を適用するか、エラーが発生した場合には実行を阻止することを意味します。これにより、ファイアウォールは常に一貫した状態になります。

さらに、nftables スクリプト環境を使用すると、次のことができます。

  • コメントの追加
  • 変数の定義
  • 他のルールセットファイルの組み込み

nftables パッケージをインストールすると、Red Hat Enterprise Linux が自動的に *.nft スクリプトを /etc/nftables/ ディレクトリーに作成します。このスクリプトには、さまざまな目的でテーブルと空のチェーンを作成するコマンドが含まれます。

21.6.2.1. 対応している nftables スクリプトの形式

nftables スクリプト環境では、次の形式でスクリプトを記述できます。

  • nft list ruleset コマンドと同じ形式でルールセットが表示されます。

    #!/usr/sbin/nft -f
    
    # Flush the rule set
    flush ruleset
    
    table inet example_table {
      chain example_chain {
        # Chain for incoming packets that drops all packets that
        # are not explicitly allowed by any rule in this chain
        type filter hook input priority 0; policy drop;
    
        # Accept connections to port 22 (ssh)
        tcp dport ssh accept
      }
    }
  • nft コマンドと同じ構文:

    #!/usr/sbin/nft -f
    
    # Flush the rule set
    flush ruleset
    
    # Create a table
    add table inet example_table
    
    # Create a chain for incoming packets that drops all packets
    # that are not explicitly allowed by any rule in this chain
    add chain inet example_table example_chain { type filter hook input priority 0 ; policy drop ; }
    
    # Add a rule that accepts connections to port 22 (ssh)
    add rule inet example_table example_chain tcp dport ssh accept

21.6.2.2. nftables スクリプトの実行

nftables スクリプトは、nft ユーティリティーに渡すか、スクリプトを直接実行することで実行できます。

手順

  • nftables スクリプトを nft ユーティリティーに渡して実行するには、次のコマンドを実行します。

    # nft -f /etc/nftables/<example_firewall_script>.nft
  • nftables スクリプトを直接実行するには、次のコマンドを実行します。

    1. 1 回だけ実行する場合:

      1. スクリプトが以下のシバンシーケンスで始まることを確認します。

        #!/usr/sbin/nft -f
        重要

        -f パラメーターを省略すると、nft ユーティリティーはスクリプトを読み込まず、Error: syntax error, unexpected newline, expecting string のように表示されます。

      2. オプション: スクリプトの所有者を root に設定します。

        # chown root /etc/nftables/<example_firewall_script>.nft
      3. 所有者のスクリプトを実行ファイルに変更します。

        # chmod u+x /etc/nftables/<example_firewall_script>.nft
    2. スクリプトを実行します。

      # /etc/nftables/<example_firewall_script>.nft

      出力が表示されない場合は、システムがスクリプトを正常に実行します。

重要

nft はスクリプトを正常に実行しますが、ルールの配置やパラメーター不足、またはスクリプト内のその他の問題により、ファイアウォールが期待通りの動作を起こさない可能性があります。

関連情報

21.6.2.3. nftables スクリプトでコメントの使用

nftables スクリプト環境は、# 文字の右側から行末までのすべてをコメントとして解釈します。

コメントは、行の先頭またはコマンドの横から開始できます。

...
# Flush the rule set
flush ruleset

add table inet example_table  # Create a table
...

21.6.2.4. nftables スクリプトでの変数の使用

nftables スクリプトで変数を定義するには、define キーワードを使用します。シングル値および匿名セットを変数に保存できます。より複雑なシナリオの場合は、セットまたは決定マップを使用します。

値を 1 つ持つ変数

以下の例は、値が enp1s0INET_DEV という名前の変数を定義します。

define INET_DEV = enp1s0

スクリプトで変数を使用するには、$ 記号と、それに続く変数名を指定します。

...
add rule inet example_table example_chain iifname $INET_DEV tcp dport ssh accept
...
匿名セットを含む変数

以下の例では、匿名セットを含む変数を定義します。

define DNS_SERVERS = { 192.0.2.1, 192.0.2.2 }

スクリプトで変数を使用するには、$ 記号と、それに続く変数名を指定します。

add rule inet example_table example_chain ip daddr $DNS_SERVERS accept
注記

中括弧は、変数がセットを表していることを示すため、ルールで使用する場合は、特別なセマンティクスを持ちます。

21.6.2.5. nftables スクリプトへのファイルの追加

nftables スクリプト環境では、include ステートメントを使用して他のスクリプトを含めることができます。

絶対パスまたは相対パスのないファイル名のみを指定すると、nftables には、デフォルトの検索パスのファイルが含まれます。これは、Red Hat Enterprise Linux では /etc に設定されています。

例21.1 デフォルト検索ディレクトリーからのファイルを含む

デフォルトの検索ディレクトリーからファイルを指定するには、次のコマンドを実行します。

include "example.nft"

例21.2 ディレクトリーの *.nft ファイルをすべて含む

*.nft で終わるすべてのファイルを /etc/nftables/rulesets/ ディレクトリーに保存するには、次のコマンドを実行します。

include "/etc/nftables/rulesets/*.nft"

include ステートメントは、ドットで始まるファイルに一致しないことに注意してください。

関連情報

  • nft(8) の man ページの Include files セクション

21.6.2.6. システムの起動時に nftables ルールの自動読み込み

systemd サービス nftables は、/etc/sysconfig/nftables.conf ファイルに含まれるファイアウォールスクリプトを読み込みます。

前提条件

  • nftables スクリプトは、/etc/nftables/ ディレクトリーに保存されます。

手順

  1. /etc/sysconfig/nftables.conf ファイルを編集します。

    • nftables パッケージのインストールで /etc/nftables/ に作成された *.nft スクリプトを変更した場合は、これらのスクリプトの include ステートメントのコメントを解除します。
    • 新しいスクリプトを作成した場合は、include ステートメントを追加してこれらのスクリプトを含めます。たとえば、nftables サービスの起動時に /etc/nftables/example.nft スクリプトを読み込むには、以下を追加します。

      include "/etc/nftables/_example_.nft"
  2. オプション: nftables サービスを開始して、システムを再起動せずにファイアウォールルールを読み込みます。

    # systemctl start nftables
  3. nftables サービスを有効にします。

    # systemctl enable nftables

21.6.3. nftables テーブル、チェーン、およびルールの作成および管理

nftables ルールセットを表示して管理できます。

21.6.3.1. nftables テーブルの基本

nftables のテーブルは、チェーン、ルール、セットなどのオブジェクトを含む名前空間です。

各テーブルにはアドレスファミリーが割り当てられている必要があります。アドレスファミリーは、このテーブルが処理するパケットタイプを定義します。テーブルを作成する際に、以下のいずれかのアドレスファミリーを設定できます。

  • ip:IPv4 パケットだけに一致します。アドレスファミリーを指定しないと、これがデフォルトになります。
  • ip6:IPv6 パケットだけに一致します。
  • inet:IPv4 パケットと IPv6 パケットの両方に一致します。
  • arp:IPv4 アドレス解決プロトコル (ARP) パケットに一致します。
  • bridge:ブリッジデバイスを通過するパケットに一致します。
  • netdev:ingress からのパケットに一致します。

テーブルを追加する場合、使用する形式はファイアウォールスクリプトにより異なります。

  • ネイティブ構文のスクリプトでは、以下を使用します。

    table <table_address_family> <table_name> {
    }
  • シェルスクリプトで、以下を使用します。

    nft add table <table_address_family> <table_name>

21.6.3.2. nftables チェーンの基本

テーブルは、ルールのコンテナーであるチェーンで構成されます。次の 2 つのルールタイプが存在します。

  • ベースチェーン:ネットワークスタックからのパケットのエントリーポイントとしてベースチェーンを使用できます。
  • 通常のチェーン:jump ターゲットとして通常のチェーンを使用し、ルールをより適切に整理できます。

ベースチェーンをテーブルに追加する場合に使用する形式は、ファイアウォールスクリプトにより異なります。

  • ネイティブ構文のスクリプトでは、以下を使用します。

    table <table_address_family> <table_name> {
      chain <chain_name> {
        type <type> hook <hook> priority <priority>
        policy <policy> ;
      }
    }
  • シェルスクリプトで、以下を使用します。

    nft add chain <table_address_family> <table_name> <chain_name> { type <type> hook <hook> priority <priority> \; policy <policy> \; }

    シェルがセミコロンをコマンドの最後として解釈しないようにするには、セミコロンの前にエスケープ文字 \ を配置します。

どちらの例でも、ベースチェーン を作成します。通常のチェーン を作成する場合、中括弧内にパラメーターを設定しないでください。

チェーンタイプ

チェーンタイプとそれらを使用できるアドレスファミリーとフックの概要を以下に示します。

タイプアドレスファミリーフック説明

filter

all

all

標準のチェーンタイプ

nat

ipip6inet

preroutinginputoutputpostrouting

このタイプのチェーンは、接続追跡エントリーに基づいてネイティブアドレス変換を実行します。最初のパケットのみがこのチェーンタイプをトラバースします。

ルート

ipip6

出力 (output)

このチェーンタイプを通過する許可済みパケットは、IP ヘッダーの関連部分が変更された場合に、新しいルートルックアップを引き起こします。

チェーンの優先度

priority パラメーターは、パケットが同じフック値を持つチェーンを通過する順序を指定します。このパラメーターは、整数値に設定することも、標準の priority 名を使用することもできます。

以下のマトリックスは、標準的な priority 名とその数値の概要、それらを使用できるファミリーおよびフックの概要です。

テキストの値数値アドレスファミリーフック

raw

-300

ipip6inet

all

mangle

-150

ipip6inet

all

dstnat

-100

ipip6inet

prerouting

-300

bridge

prerouting

filter

0

ipip6inetarpnetdev

all

-200

bridge

all

security

50

ipip6inet

all

srcnat

100

ipip6inet

postrouting

300

bridge

postrouting

out

100

bridge

出力 (output)

チェーンポリシー

チェーンポリシーは、このチェーンのルールでアクションが指定されていない場合に、nftables がパケットを受け入れるかドロップするかを定義します。チェーンには、以下のいずれかのポリシーを設定できます。

  • accept (デフォルト)
  • drop

21.6.3.3. nftables ルールの基本

ルールは、このルールを含むチェーンを渡すパケットに対して実行するアクションを定義します。ルールに一致する式も含まれる場合、nftables は、以前の式がすべて適用されている場合にのみアクションを実行します。

チェーンにルールを追加する場合、使用する形式はファイアウォールスクリプトにより異なります。

  • ネイティブ構文のスクリプトでは、以下を使用します。

    table <table_address_family> <table_name> {
      chain <chain_name> {
        type <type> hook <hook> priority <priority> ; policy <policy> ;
          <rule>
      }
    }
  • シェルスクリプトで、以下を使用します。

    nft add rule <table_address_family> <table_name> <chain_name> <rule>

    このシェルコマンドは、チェーンの最後に新しいルールを追加します。チェーンの先頭にルールを追加する場合は、nft add の代わりに nft insert コマンドを使用します。

21.6.3.4. nft コマンドを使用したテーブル、チェーン、ルールの管理

コマンドラインまたはシェルスクリプトで nftables ファイアウォールを管理するには、nft ユーティリティーを使用します。

重要

この手順のコマンドは通常のワークフローを表しておらず、最適化されていません。この手順では、nft コマンドを使用して、一般的なテーブル、チェーン、およびルールを管理する方法を説明します。

手順

  1. テーブルが IPv4 パケットと IPv6 パケットの両方を処理できるように、inet アドレスファミリーを使用して nftables_svc という名前のテーブルを作成します。

    # nft add table inet nftables_svc
  2. 受信ネットワークトラフィックを処理する INPUT という名前のベースチェーンを inet nftables_svc テーブルに追加します。

    # nft add chain inet nftables_svc INPUT { type filter hook input priority filter \; policy accept \; }

    シェルがセミコロンをコマンドの最後として解釈しないようにするには、\ 文字を使用してセミコロンをエスケープします。

  3. INPUT チェーンにルールを追加します。たとえば、INPUT チェーンの最後のルールとして、ポート 22 および 443 で着信 TCP トラフィックを許可し、Internet Control Message Protocol (ICMP)ポートに到達できないメッセージで他の着信トラフィックを拒否します。

    # nft add rule inet nftables_svc INPUT tcp dport 22 accept
    # nft add rule inet nftables_svc INPUT tcp dport 443 accept
    # nft add rule inet nftables_svc INPUT reject with icmpx type port-unreachable

    ここで示されたように nft add rule コマンドを実行すると、nft はコマンド実行と同じ順序でルールをチェーンに追加します。

  4. ハンドルを含む現在のルールセットを表示します。

    # nft -a list table inet nftables_svc
    table inet nftables_svc { # handle 13
      chain INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        tcp dport 22 accept # handle 2
        tcp dport 443 accept # handle 3
        reject # handle 4
      }
    }
  5. ハンドル 3 で既存ルールの前にルールを挿入します。たとえば、ポート 636 で TCP トラフィックを許可するルールを挿入するには、以下を入力します。

    # nft insert rule inet nftables_svc INPUT position 3 tcp dport 636 accept
  6. ハンドル 3 で、既存ルールの後ろにルールを追加します。たとえば、ポート 80 で TCP トラフィックを許可するルールを追加するには、以下を入力します。

    # nft add rule inet nftables_svc INPUT position 3 tcp dport 80 accept
  7. ハンドルでルールセットを再表示します。後で追加したルールが指定の位置に追加されていることを確認します。

    # nft -a list table inet nftables_svc
    table inet nftables_svc { # handle 13
      chain INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        tcp dport 22 accept # handle 2
        tcp dport 636 accept # handle 5
        tcp dport 443 accept # handle 3
        tcp dport 80 accept # handle 6
        reject # handle 4
      }
    }
  8. ハンドル 6 でルールを削除します。

    # nft delete rule inet nftables_svc INPUT handle 6

    ルールを削除するには、ハンドルを指定する必要があります。

  9. ルールセットを表示し、削除されたルールがもう存在しないことを確認します。

    # nft -a list table inet nftables_svc
    table inet nftables_svc { # handle 13
      chain INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        tcp dport 22 accept # handle 2
        tcp dport 636 accept # handle 5
        tcp dport 443 accept # handle 3
        reject # handle 4
      }
    }
  10. INPUT チェーンから残りのルールをすべて削除します。

    # nft flush chain inet nftables_svc INPUT
  11. ルールセットを表示し、INPUT チェーンが空であることを確認します。

    # nft list table inet nftables_svc
    table inet nftables_svc {
      chain INPUT {
        type filter hook input priority filter; policy accept
      }
    }
  12. INPUT チェーンを削除します。

    # nft delete chain inet nftables_svc INPUT

    このコマンドを使用して、まだルールが含まれているチェーンを削除することもできます。

  13. ルールセットを表示し、INPUT チェーンが削除されたことを確認します。

    # nft list table inet nftables_svc
    table inet nftables_svc {
    }
  14. nftables_svc テーブルを削除します。

    # nft delete table inet nftables_svc

    このコマンドを使用して、まだルールが含まれているテーブルを削除することもできます。

    注記

    ルールセット全体を削除するには、個別のコマンドですべてのルール、チェーン、およびテーブルを手動で削除するのではなく、nft flush ruleset コマンドを使用します。

関連情報

nft(8) の man ページ

21.6.4. nftables を使用した NAT の設定

nftables を使用すると、以下のネットワークアドレス変換 (NAT) タイプを設定できます。

  • マスカレーディング
  • ソース NAT (SNAT)
  • 宛先 NAT (DNAT)
  • リダイレクト
重要

iifname パラメーターおよび oifname パラメーターでは実インターフェイス名のみを使用でき、代替名 (altname) には対応していません。

21.6.4.1. NAT タイプ

以下は、ネットワークアドレス変換 (NAT) タイプになります。

マスカレードおよびソースの NAT (SNAT)

この NAT タイプのいずれかを使用して、パケットのソース IP アドレスを変更します。たとえば、インターネットサービスプロバイダーは、プライベート IP 範囲 (10.0.0.0/8 など) をルーティングしません。ネットワークでプライベート IP 範囲を使用し、ユーザーがインターネット上のサーバーにアクセスできるようにする必要がある場合は、この範囲のパケットのソース IP アドレスをパブリック IP アドレスにマップします。

マスカレードと SNAT は互いに非常に似ています。相違点は次のとおりです。

  • マスカレードは、出力インターフェイスの IP アドレスを自動的に使用します。したがって、出力インターフェイスが動的 IP アドレスを使用する場合は、マスカレードを使用します。
  • SNAT は、パケットのソース IP アドレスを指定された IP に設定し、出力インターフェイスの IP アドレスを動的に検索しません。そのため、SNAT の方がマスカレードよりも高速です。出力インターフェイスが固定 IP アドレスを使用する場合は、SNAT を使用します。
宛先 NAT (DNAT)
この NAT タイプを使用して、着信パケットの宛先アドレスとポートを書き換えます。たとえば、Web サーバーがプライベート IP 範囲の IP アドレスを使用しているため、インターネットから直接アクセスできない場合は、ルーターに DNAT ルールを設定し、着信トラフィックをこのサーバーにリダイレクトできます。
リダイレクト
このタイプは、チェーンフックに応じてパケットをローカルマシンにリダイレクトする DNAT の特殊なケースです。たとえば、サービスが標準ポートとは異なるポートで実行する場合は、標準ポートからこの特定のポートに着信トラフィックをリダイレクトすることができます。

21.6.4.2. nftables を使用したマスカレードの設定

マスカレードを使用すると、ルーターは、インターフェイスを介して送信されるパケットのソース IP を、インターフェイスの IP アドレスに動的に変更できます。これは、インターフェイスに新しい IP が割り当てられている場合に、nftables はソース IP の置き換え時に新しい IP を自動的に使用することを意味します。

ens3 インターフェイスを介してホストから出るパケットの送信元 IP を、ens3 で設定された IP に置き換えます。

手順

  1. テーブルを作成します。

    # nft add table nat
  2. テーブルに、prerouting チェーンおよび postrouting チェーンを追加します。

    # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
    重要

    prerouting チェーンにルールを追加しなくても、nftables フレームワークでは、着信パケット返信に一致するようにこのチェーンが必要になります。

    -- オプションを nft コマンドに渡して、シェルが負の priority 値を nft コマンドのオプションとして解釈しないようにする必要があることに注意してください。

  3. postrouting チェーンに、ens3 インターフェイスの出力パケットに一致するルールを追加します。

    # nft add rule nat postrouting oifname "ens3" masquerade

21.6.4.3. nftables を使用したソース NAT の設定

ルーターでは、ソース NAT (SNAT) を使用して、インターフェイスを介して特定の IP アドレスに送信するパケットの IP を変更できます。次に、ルーターは送信パケットのソース IP を置き換えます。

手順

  1. テーブルを作成します。

    # nft add table nat
  2. テーブルに、prerouting チェーンおよび postrouting チェーンを追加します。

    # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
    重要

    postrouting チェーンにルールを追加しなくても、nftables フレームワークでは、このチェーンが発信パケット返信に一致するようにする必要があります。

    -- オプションを nft コマンドに渡して、シェルが負の priority 値を nft コマンドのオプションとして解釈しないようにする必要があることに注意してください。

  3. ens3 を介した発信パケットのソース IP を 192.0.2.1 に置き換えるルールを postrouting チェーンに追加します。

    # nft add rule nat postrouting oifname "ens3" snat to 192.0.2.1

21.6.4.4. nftables を使用した宛先 NAT の設定

宛先 NAT (DNAT)を使用すると、ルーター上のトラフィックをインターネットから直接アクセスできないホストにリダイレクトできます。

たとえば、DNAT を使用すると、ルーターはポート 80 および 443 に送信された受信トラフィックを、IP アドレス 192.0.2.1 の Web サーバーにリダイレクトします。

手順

  1. テーブルを作成します。

    # nft add table nat
  2. テーブルに、prerouting チェーンおよび postrouting チェーンを追加します。

    # nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
    # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
    重要

    postrouting チェーンにルールを追加しなくても、nftables フレームワークでは、このチェーンが発信パケット返信に一致するようにする必要があります。

    -- オプションを nft コマンドに渡して、シェルが負の priority 値を nft コマンドのオプションとして解釈しないようにする必要があることに注意してください。

  3. prerouting チェーンに、ルーターの ens3 インターフェイスのポート 80 および 443 に受信トラフィックを、IP アドレス 192.0.2.1 を持つ Web サーバーにリダイレクトするルールを追加します。

    # nft add rule nat prerouting iifname ens3 tcp dport { 80, 443 } dnat to 192.0.2.1
  4. 環境に応じて、SNAT ルールまたはマスカレードルールを追加して、Web サーバーから返されるパケットのソースアドレスを送信者に変更します。

    1. ens3 インターフェイスが動的 IP アドレスを使用している場合は、マスカレードルールを追加します。

      # nft add rule nat postrouting oifname "ens3" masquerade
    2. ens3 インターフェイスが静的 IP アドレスを使用する場合は、SNAT ルールを追加します。たとえば、ens3 が IP アドレス 198.51.100.1 を使用している場合は、以下のようになります。

      # nft add rule nat postrouting oifname "ens3" snat to 198.51.100.1
  5. パケット転送を有効にします。

    # echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
    # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

関連情報

21.6.4.5. nftables を使用したリダイレクトの設定

redirect 機能は、チェーンフックに応じてパケットをローカルマシンにリダイレクトする宛先ネットワークアドレス変換 (DNAT) の特殊なケースです。

たとえば、ローカルホストのポート 22 に送信された着信および転送されたトラフィックを 2222 ポートにリダイレクトすることができます。

手順

  1. テーブルを作成します。

    # nft add table nat
  2. テーブルに prerouting チェーンを追加します。

    # nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }

    -- オプションを nft コマンドに渡して、シェルが負の priority 値を nft コマンドのオプションとして解釈しないようにする必要があることに注意してください。

  3. 22 ポートの着信トラフィックを 2222 ポートにリダイレクトするルールを prerouting チェーンに追加します。

    # nft add rule nat prerouting tcp dport 22 redirect to 2222

関連情報

21.6.5. nftables コマンドでのセットの使用

nftables フレームワークは、セットをネイティブに対応します。たとえば、ルールが複数の IP アドレス、ポート番号、インターフェイス、またはその他の一致基準に一致する必要がある場合など、セットを使用できます。

21.6.5.1. nftables での匿名セットの使用

匿名セットには、ルールで直接使用する { 22, 80, 443 } などの中括弧で囲まれたコンマ区切りの値が含まれます。IP アドレスやその他の一致基準にも匿名セットを使用できます。

匿名セットの欠点は、セットを変更する場合はルールを置き換える必要があることです。動的なソリューションの場合は、nftables で名前付きセットの使用 で説明されているように名前付きセットを使用します。

前提条件

  • inet ファミリーに example_chain チェーンおよび example_table テーブルがある。

手順

  1. たとえば、ポート 2280、および 443 に着信トラフィックを許可するルールを、example_tableexample_chain に追加するには、次のコマンドを実行します。

    # nft add rule inet example_table example_chain tcp dport { 22, 80, 443 } accept
  2. オプション: example_table 内のすべてのチェーンとそのルールを表示します。

    # nft list table inet example_table
    table inet example_table {
      chain example_chain {
        type filter hook input priority filter; policy accept;
        tcp dport { ssh, http, https } accept
      }
    }

21.6.5.2. nftables で名前付きセットの使用

nftables フレームワークは、変更可能な名前付きセットに対応します。名前付きセットは、テーブル内の複数のルールで使用できる要素のリストまたは範囲です。匿名セットに対する別の利点として、セットを使用するルールを置き換えることなく、名前付きセットを更新できます。

名前付きセットを作成する場合は、セットに含まれる要素のタイプを指定する必要があります。以下のタイプを設定できます。

  • 192.0.2.1192.0.2.0/24 など、IPv4 アドレスまたは範囲を含むセットの場合は ipv4_addr
  • 2001:db8:1::12001:db8:1::1/64 など、IPv6 アドレスまたは範囲を含むセットの場合は ipv6_addr
  • 52:54:00:6b:66:42 など、メディアアクセス制御 (MAC) アドレスの一覧を含むセットの場合は ether_addr
  • tcp など、インターネットプロトコルタイプの一覧が含まれるセットの場合は inet_proto
  • ssh など、インターネットサービスの一覧を含むセットの場合は inet_service
  • パケットマークの一覧を含むセットの場合は mark。パケットマークは、任意の 32 ビットの正の整数値 (0 から 2147483647) にすることができます。

前提条件

  • example_chain チェーンと example_table テーブルが存在する。

手順

  1. 空のファイルを作成します。以下の例では、IPv4 アドレスのセットを作成します。

    • 複数の IPv4 アドレスを格納することができるセットを作成するには、次のコマンドを実行します。

      # nft add set inet example_table example_set { type ipv4_addr \; }
    • IPv4 アドレス範囲を保存できるセットを作成するには、次のコマンドを実行します。

      # nft add set inet example_table example_set { type ipv4_addr \; flags interval \; }
    重要

    シェルがセミコロンをコマンドの終わりとして解釈しないようにするには、バックスラッシュでセミコロンをエスケープする必要があります。

  2. オプション: セットを使用するルールを作成します。たとえば、次のコマンドは、example_set の IPv4 アドレスからのパケットをすべて破棄するルールを、example_tableexample_chain に追加します。

    # nft add rule inet example_table example_chain ip saddr @example_set drop

    example_set が空のままなので、ルールには現在影響がありません。

  3. IPv4 アドレスを example_set に追加します。

    • 個々の IPv4 アドレスを保存するセットを作成する場合は、次のコマンドを実行します。

      # nft add element inet example_table example_set { 192.0.2.1, 192.0.2.2 }
    • IPv4 範囲を保存するセットを作成する場合は、次のコマンドを実行します。

      # nft add element inet example_table example_set { 192.0.2.0-192.0.2.255 }

      IP アドレス範囲を指定する場合は、上記の例の 192.0.2.0/24 のように、CIDR (Classless Inter-Domain Routing) 表記を使用することもできます。

21.6.5.3. 関連情報

  • nft(8) の man ページの Sets セクション

21.6.6. nftables コマンドにおける決定マップの使用

ディクショナリーとしても知られている決定マップにより、nft は一致基準をアクションにマッピングすることで、パケット情報に基づいてアクションを実行できます。

21.6.6.1. nftables での匿名マップの使用

匿名マップは、ルールで直接使用する { match_criteria : action } ステートメントです。ステートメントには、複数のコンマ区切りマッピングを含めることができます。

匿名マップの欠点は、マップを変更する場合には、ルールを置き換える必要があることです。動的なソリューションの場合は、nftables での名前付きマップの使用 で説明されているように名前付きマップを使用します。

たとえば、匿名マップを使用して、IPv4 プロトコルおよび IPv6 プロトコルの TCP パケットと UDP パケットの両方を異なるチェーンにルーティングし、着信 TCP パケットと UDP パケットを個別にカウントできます。

手順

  1. 新しいテーブルを作成します。

    # nft add table inet example_table
  2. example_tabletcp_packets チェーンを作成します。

    # nft add chain inet example_table tcp_packets
  3. このチェーンのトラフィックをカウントする tcp_packets にルールを追加します。

    # nft add rule inet example_table tcp_packets counter
  4. example_tableudp_packets チェーンを作成します。

    # nft add chain inet example_table udp_packets
  5. このチェーンのトラフィックをカウントする udp_packets にルールを追加します。

    # nft add rule inet example_table udp_packets counter
  6. 着信トラフィックのチェーンを作成します。たとえば、example_table に、着信トラフィックをフィルタリングする incoming_traffic という名前のチェーンを作成するには、次のコマンドを実行します。

    # nft add chain inet example_table incoming_traffic { type filter hook input priority 0 \; }
  7. 匿名マップを持つルールを incoming_traffic に追加します。

    # nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }

    匿名マップはパケットを区別し、プロトコルに基づいて別のカウンターチェーンに送信します。

  8. トラフィックカウンターの一覧を表示する場合は、example_table を表示します。

    # nft list table inet example_table
    table inet example_table {
      chain tcp_packets {
        counter packets 36379 bytes 2103816
      }
    
      chain udp_packets {
        counter packets 10 bytes 1559
      }
    
      chain incoming_traffic {
        type filter hook input priority filter; policy accept;
        ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
      }
    }

    tcp_packets チェーンおよび udp_packets チェーンのカウンターは、受信パケットとバイトの両方を表示します。

21.6.6.2. nftables での名前付きマップの使用

nftables フレームワークは、名前付きマップに対応します。テーブルの複数のルールでこのマップを使用できます。匿名マップに対する別の利点は、名前付きマップを使用するルールを置き換えることなく、名前付きマップを更新できることです。

名前付きマップを作成する場合は、要素のタイプを指定する必要があります。

  • 一致する部分に 192.0.2.1 などの IPv4 アドレスが含まれるマップの場合は ipv4_addr
  • 一致する部分に 2001:db8:1::1 などの IPv6 アドレスが含まれるマップの場合は ipv6_addr
  • 52:54:00:6b:66:42 などのメディアアクセス制御 (MAC) アドレスを含むマップの場合は ether_addr
  • 一致する部分に tcp などのインターネットプロトコルタイプが含まれるマップの場合は inet_proto
  • 一致する部分に ssh22 などのインターネットサービス名のポート番号が含まれるマップの場合は inet_service
  • 一致する部分にパケットマークが含まれるマップの場合は mark。パケットマークは、任意の正の 32 ビットの整数値 (0 ~ 2147483647) にできます。
  • 一致する部分にカウンターの値が含まれるマップの場合は counter。カウンター値は、正の値の 64 ビットであれば任意の値にすることができます。
  • 一致する部分にクォータ値が含まれるマップの場合は quota。クォータの値は、64 ビットの整数値にできます。

たとえば、送信元 IP アドレスに基づいて着信パケットを許可または拒否できます。名前付きマップを使用すると、このシナリオを設定するのに必要なルールは 1 つだけで、IP アドレスとアクションがマップに動的に保存されます。

手順

  1. テーブルを作成します。たとえば、IPv4 パケットを処理する example_table という名前のテーブルを作成するには、次のコマンドを実行します。

    # nft add table ip example_table
  2. チェーンを作成します。たとえば、example_table に、example_chain という名前のチェーンを作成するには、次のコマンドを実行します。

    # nft add chain ip example_table example_chain { type filter hook input priority 0 \; }
    重要

    シェルがセミコロンをコマンドの終わりとして解釈しないようにするには、バックスラッシュでセミコロンをエスケープする必要があります。

  3. 空のマップを作成します。たとえば、IPv4 アドレスのマッピングを作成するには、次のコマンドを実行します。

    # nft add map ip example_table example_map { type ipv4_addr : verdict \; }
  4. マップを使用するルールを作成します。たとえば、次のコマンドは、両方とも example_map で定義されている IPv4 アドレスにアクションを適用するルールを、 example_tableexample_chain に追加します。

    # nft add rule example_table example_chain ip saddr vmap @example_map
  5. IPv4 アドレスと対応するアクションを example_map に追加します。

    # nft add element ip example_table example_map { 192.0.2.1 : accept, 192.0.2.2 : drop }

    以下の例では、IPv4 アドレスのアクションへのマッピングを定義します。上記で作成したルールと組み合わせて、ファイアウォールは 192.0.2.1 からのパケットを許可し、192.0.2.2 からのパケットを破棄します。

  6. オプション: 別の IP アドレスおよび action ステートメントを追加してマップを拡張します。

    # nft add element ip example_table example_map { 192.0.2.3 : accept }
  7. オプション: マップからエントリーを削除します。

    # nft delete element ip example_table example_map { 192.0.2.1 }
  8. オプション: ルールセットを表示します。

    # nft list ruleset
    table ip example_table {
      map example_map {
        type ipv4_addr : verdict
        elements = { 192.0.2.2 : drop, 192.0.2.3 : accept }
      }
    
      chain example_chain {
        type filter hook input priority filter; policy accept;
        ip saddr vmap @example_map
      }
    }

21.6.6.3. 関連情報

  • nft(8) の man ページの Maps セクション

21.6.7. 以下に例を示します。nftables スクリプトを使用した LAN および DMZ の保護

RHEL ルーターで nftables フレームワークを使用して、内部 LAN 内のネットワーククライアントと DMZ の Web サーバーを、インターネットやその他のネットワークからの不正アクセスから保護するファイアウォールスクリプトを作成およびインストールします。

重要

この例はデモ目的専用で、特定の要件があるシナリオを説明しています。

ファイアウォールスクリプトは、ネットワークインフラストラクチャーとセキュリティー要件に大きく依存します。この例を使用して、独自の環境用のスクリプトを作成する際に nftables ファイアウォールの概念を理解してください。

21.6.7.1. ネットワークの状態

この例のネットワークは、以下の条件下にあります。

  • ルーターは以下のネットワークに接続されています。

    • インターフェイス enp1s0を介したインターネット
    • インターフェイス enp7s0を介した内部 LAN
    • enp8s0までの DMZ
  • ルーターのインターネットインターフェイスには、静的 IPv4 アドレス (203.0.113.1) と IPv6 アドレス (2001:db8:a::1) の両方が割り当てられています。
  • 内部 LAN のクライアントは 10.0.0.0/24 の範囲のプライベート IPv4 アドレスのみを使用します。その結果、LAN からインターネットへのトラフィックには、送信元ネットワークアドレス変換 (SNAT) が必要です。
  • 内部 LAN の管理者用 PC は、IP アドレス 10.0.0.100 および 10.0.0.200 を使用します。
  • DMZ は、198.51.100.0/24 および 2001:db8:b::/56 の範囲のパブリック IP アドレスを使用します。
  • DMZ の Web サーバーは、IP アドレス 198.51.100.5 および 2001:db8:b::5 を使用します。
  • ルーターは、LAN および DMZ 内のホストのキャッシング DNS サーバーとして機能します。

21.6.7.2. ファイアウォールスクリプトのセキュリティー要件

以下は、サンプルネットワークにおける nftables ファイアウォールの要件です。

  • ルーターは以下を実行できる必要があります。

    • DNS クエリーを再帰的に解決します。
    • ループバックインターフェイスですべての接続を実行します。
  • 内部 LAN のクライアントは以下を実行できる必要があります。

    • ルーターで実行しているキャッシング DNS サーバーをクエリーします。
    • DMZ の HTTPS サーバーにアクセスします。
    • インターネット上の任意の HTTPS サーバーにアクセスします。
  • 管理者用の PC は、SSH を使用してルーターと DMZ 内のすべてのサーバーにアクセスできる必要があります。
  • DMZ の Web サーバーは以下を実行できる必要があります。

    • ルーターで実行しているキャッシング DNS サーバーをクエリーします。
    • インターネット上の HTTPS サーバーにアクセスして更新をダウンロードします。
  • インターネット上のホストは以下を実行できる必要があります。

    • DMZ の HTTPS サーバーにアクセスします。
  • さらに、以下のセキュリティー要件が存在します。

    • 明示的に許可されていない接続の試行はドロップする必要があります。
    • ドロップされたパケットはログに記録する必要があります。

21.6.7.3. ドロップされたパケットをファイルにロギングするための設定

デフォルトでは、systemd は、ドロップされたパケットなどのカーネルメッセージをジャーナルに記録します。さらに、このようなエントリーを別のファイルに記録するように rsyslog サービスを設定することもできます。ログファイルが無限に大きくならないようにするために、ローテーションポリシーを設定します。

前提条件

  • rsyslog パッケージがインストールされている。
  • rsyslog サービスが実行されている。

手順

  1. 以下の内容で /etc/rsyslog.d/nftables.conf ファイルを作成します。

    :msg, startswith, "nft drop" -/var/log/nftables.log
    & stop

    この設定を使用すると、rsyslog サービスはドロップされたパケットを /var/log/messages ではなく /var/log/nftables.log ファイルに記録します。

  2. rsyslog サービスを再起動します。

    # systemctl restart rsyslog
  3. サイズが 10 MB を超える場合は、以下の内容で /etc/logrotate.d/nftables ファイルを作成し、/var/log/nftables.log をローテーションします。

    /var/log/nftables.log {
      size +10M
      maxage 30
      sharedscripts
      postrotate
        /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
      endscript
    }

    maxage 30 設定は、次のローテーション操作中に logrotate が 30 日経過したローテーション済みログを削除することを定義します。

関連情報

  • rsyslog.conf(5) の man ページ
  • logrotate(8) の man ページ

21.6.7.4. nftables スクリプトの作成とアクティブ化

この例は、RHEL ルーターで実行され、DMZ の内部 LAN および Web サーバーのクライアントを保護する nftables ファイアウォールスクリプトです。この例で使用されているネットワークとファイアウォールの要件について、詳しくはファイアウォールスクリプトの ネットワークの状態 および ファイアウォールスクリプトのセキュリティー要件 を参照してください。

警告

この nftables ファイアウォールスクリプトは、デモ専用です。お使いの環境やセキュリティー要件に適応させて使用してください。

前提条件

手順

  1. 以下の内容で /etc/nftables/firewall.nft スクリプトを作成します。

    # Remove all rules
    flush ruleset
    
    
    # Table for both IPv4 and IPv6 rules
    table inet nftables_svc {
    
      # Define variables for the interface name
      define INET_DEV = enp1s0
      define LAN_DEV  = enp7s0
      define DMZ_DEV  = enp8s0
    
    
      # Set with the IPv4 addresses of admin PCs
      set admin_pc_ipv4 {
        type ipv4_addr
        elements = { 10.0.0.100, 10.0.0.200 }
      }
    
    
      # Chain for incoming trafic. Default policy: drop
      chain INPUT {
        type filter hook input priority filter
        policy drop
    
        # Accept packets in established and related state, drop invalid packets
        ct state vmap { established:accept, related:accept, invalid:drop }
    
        # Accept incoming traffic on loopback interface
        iifname lo accept
    
        # Allow request from LAN and DMZ to local DNS server
        iifname { $LAN_DEV, $DMZ_DEV } meta l4proto { tcp, udp } th dport 53 accept
    
        # Allow admins PCs to access the router using SSH
        iifname $LAN_DEV ip saddr @admin_pc_ipv4 tcp dport 22 accept
    
        # Last action: Log blocked packets
        # (packets that were not accepted in previous rules in this chain)
        log prefix "nft drop IN : "
      }
    
    
      # Chain for outgoing traffic. Default policy: drop
      chain OUTPUT {
        type filter hook output priority filter
        policy drop
    
        # Accept packets in established and related state, drop invalid packets
        ct state vmap { established:accept, related:accept, invalid:drop }
    
        # Accept outgoing traffic on loopback interface
        oifname lo accept
    
        # Allow local DNS server to recursively resolve queries
        oifname $INET_DEV meta l4proto { tcp, udp } th dport 53 accept
    
        # Last action: Log blocked packets
        log prefix "nft drop OUT: "
      }
    
    
      # Chain for forwarding traffic. Default policy: drop
      chain FORWARD {
        type filter hook forward priority filter
        policy drop
    
        # Accept packets in established and related state, drop invalid packets
        ct state vmap { established:accept, related:accept, invalid:drop }
    
        # IPv4 access from LAN and Internet to the HTTPS server in the DMZ
        iifname { $LAN_DEV, $INET_DEV } oifname $DMZ_DEV ip daddr 198.51.100.5 tcp dport 443 accept
    
        # IPv6 access from Internet to the HTTPS server in the DMZ
        iifname $INET_DEV oifname $DMZ_DEV ip6 daddr 2001:db8:b::5 tcp dport 443 accept
    
        # Access from LAN and DMZ to HTTPS servers on the Internet
        iifname { $LAN_DEV, $DMZ_DEV } oifname $INET_DEV tcp dport 443 accept
    
        # Last action: Log blocked packets
        log prefix "nft drop FWD: "
      }
    
    
      # Postrouting chain to handle SNAT
      chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
    
        # SNAT for IPv4 traffic from LAN to Internet
        iifname $LAN_DEV oifname $INET_DEV snat ip to 203.0.113.1
      }
    }
  2. /etc/nftables/firewall.nft スクリプトを /etc/sysconfig/nftables.conf ファイルに追加します。

    include "/etc/nftables/firewall.nft"
  3. IPv4 転送を有効にします。

    # echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
    # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
  4. nftables サービスを有効にして起動します。

    # systemctl enable --now nftables

検証

  1. オプション: nftables ルールセットを確認します。

    # nft list ruleset
    ...
  2. ファイアウォールが阻止するアクセスの実行を試みます。たとえば、DMZ から SSH を使用してルーターにアクセスします。

    # ssh router.example.com
    ssh: connect to host router.example.com port 22: Network is unreachable
  3. ロギング設定に応じて、以下を検索します。

    • ブロックされたパケットの systemd ジャーナル:

      # journalctl -k -g "nft drop"
      Oct 14 17:27:18 router kernel: nft drop IN : IN=enp8s0 OUT= MAC=... SRC=198.51.100.5 DST=198.51.100.1 ... PROTO=TCP SPT=40464 DPT=22 ... SYN ...
    • ブロックされたパケットの /var/log/nftables.log ファイル:

      Oct 14 17:27:18 router kernel: nft drop IN : IN=enp8s0 OUT= MAC=... SRC=198.51.100.5 DST=198.51.100.1 ... PROTO=TCP SPT=40464 DPT=22 ... SYN ...

21.6.8. nftables を使用したポート転送の設定

ポート転送を使用すると、管理者は特定の宛先ポートに送信されたパケットを、別のローカルまたはリモートポートに転送できます。

たとえば、Web サーバーにパブリック IP アドレスがない場合は、ファイアウォールの 80 ポートおよび 443 ポートの着信パケットを Web サーバーに転送するファイアウォールのポート転送ルールを設定できます。このファイアウォールルールを使用すると、インターネットのユーザーは、ファイアウォールの IP またはホスト名を使用して Web サーバーにアクセスできます。

21.6.8.1. 着信パケットの別のローカルポートへの転送

nftables を使用してパケットを転送できます。たとえば、ポート 8022 の着信 IPv4 パケットを、ローカルシステムのポート 22 に転送できます。

手順

  1. ip アドレスファミリーを使用して、nat という名前のテーブルを作成します。

    # nft add table ip nat
  2. テーブルに、prerouting チェーンおよび postrouting チェーンを追加します。

    # nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
    注記

    -- オプションを nft コマンドに渡して、シェルが負の priority 値を nft コマンドのオプションとして解釈しないようにします。

  3. 8022 ポートの着信パケットを、ローカルポート 22 にリダイレクトするルールを prerouting チェーンに追加します。

    # nft add rule ip nat prerouting tcp dport 8022 redirect to :22

21.6.8.2. 特定のローカルポートで着信パケットを別のホストに転送

宛先ネットワークアドレス変換 (DNAT) ルールを使用して、ローカルポートの着信パケットをリモートホストに転送できます。これにより、インターネット上のユーザーは、プライベート IP アドレスを持つホストで実行しているサービスにアクセスできるようになります。

たとえば、ローカルポート 443 の着信 IPv4 パケットを、IP アドレス 192.0.2.1 を持つリモートシステムの同じポート番号に転送できます。

前提条件

  • パケットを転送するシステムに root ユーザーとしてログインしている。

手順

  1. ip アドレスファミリーを使用して、nat という名前のテーブルを作成します。

    # nft add table ip nat
  2. テーブルに、prerouting チェーンおよび postrouting チェーンを追加します。

    # nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
    # nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
    注記

    -- オプションを nft コマンドに渡して、シェルが負の priority 値を nft コマンドのオプションとして解釈しないようにします。

  3. 443 ポートの着信パケットを 192.0.2.1 上の同じポートにリダイレクトするルールを prerouting チェーンに追加します。

    # nft add rule ip nat prerouting tcp dport 443 dnat to 192.0.2.1
  4. 出力トラフィックをマスカレードするルールを postrouting チェーンに追加します。

    # nft add rule ip nat postrouting daddr 192.0.2.1 masquerade
  5. パケット転送を有効にします。

    # echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
    # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

21.6.9. nftables を使用した接続の量の制限

nftables を使用して、接続の数を制限したり、一定の数の接続の確立を試みる IP アドレスをブロックして、システムリソースを過剰に使用されないようにします。

21.6.9.1. nftables を使用した接続数の制限

nft ユーティリティーの ct count パラメーターを使用すると、管理者は接続数を制限することができます。

前提条件

  • example_table にベースの example_chain が存在する。

手順

  1. IPv4 アドレスの動的セットを作成します。

    # nft add set inet example_table example_meter { type ipv4_addr\; flags dynamic \;}
  2. IPv4 アドレスから SSH ポート (22) への 2 つの同時接続のみを許可し、同じ IP からのすべての接続を拒否するルールを追加します。

    # nft add rule ip example_table example_chain tcp dport ssh meter example_meter { ip saddr ct count over 2 } counter reject
  3. オプション: 前の手順で作成したセットを表示します。

    # nft list set inet example_table example_meter
    table inet example_table {
      meter example_meter {
        type ipv4_addr
        size 65535
        elements = { 192.0.2.1 ct count over 2 , 192.0.2.2 ct count over 2  }
      }
    }

    elements エントリーは、現時点でルールに一致するアドレスを表示します。この例では、elements は、SSH ポートへのアクティブな接続がある IP アドレスを一覧表示します。出力には、アクティブな接続の数を表示しないため、接続が拒否された場合は表示されないことに注意してください。

21.6.9.2. 1 分以内に新しい着信 TCP 接続を 11 個以上試行する IP アドレスのブロック

1 分以内に 11 個以上の IPv4 TCP 接続を確立しているホストを一時的にブロックできます。

手順

  1. ip アドレスファミリーを使用して filter テーブルを作成します。

    # nft add table ip filter
  2. input チェーンを filter テーブルに追加します。

    # nft add chain ip filter input { type filter hook input priority 0 \; }
  3. 1 分以内に 10 を超える TCP 接続を確立しようとするソースアドレスからのすべてのパケットを破棄するルールを追加します。

    # nft add rule ip filter input ip protocol tcp ct state new, untracked meter ratemeter { ip saddr timeout 5m limit rate over 10/minute } drop

    timeout 5m パラメーターは、nftables が、メーターが古いエントリーで一杯にならないように、5 分後にエントリーを自動的に削除することを定義します。

検証

  • メーターのコンテンツを表示するには、以下のコマンドを実行します。

    # nft list meter ip filter ratemeter
    table ip filter {
      meter ratemeter {
        type ipv4_addr
        size 65535
        flags dynamic,timeout
        elements = { 192.0.2.1 limit rate over 10/minute timeout 5m expires 4m58s224ms }
      }
    }

21.6.10. nftables ルールのデバッグ

nftables フレームワークは、管理者がルールをデバッグし、パケットがそれに一致するかどうかを確認するためのさまざまなオプションを提供します。

21.6.10.1. カウンターによるルールの作成

ルールが一致しているかどうかを確認するには、カウンターを使用できます。

  • 既存のルールにカウンターを追加する手順の詳細は、Configuring and managing networkingAdding a counter to an existing rule を参照してください。

前提条件

  • ルールを追加するチェーンが存在する。

手順

  1. counter パラメーターで新しいルールをチェーンに追加します。以下の例では、ポート 22 で TCP トラフィックを許可し、このルールに一致するパケットとトラフィックをカウントするカウンターを使用するルールを追加します。

    # nft add rule inet example_table example_chain tcp dport 22 *counter accept*
  2. カウンター値を表示するには、次のコマンドを実行します。

    # nft list ruleset
    table inet example_table {
      chain example_chain {
        type filter hook input priority filter; policy accept;
        tcp dport ssh counter packets 6872 bytes 105448565 accept
      }
    }

21.6.10.2. 既存のルールへのカウンターの追加

ルールが一致しているかどうかを確認するには、カウンターを使用できます。

  • カウンターで新しいルールを追加する手順の詳細は、Configuring and managing networkingCreating a rule with the counter を参照してください。

前提条件

  • カウンターを追加するルールがある。

手順

  1. チェーンのルール (ハンドルを含む) を表示します。

    # nft --handle list chain inet example_table example_chain
    table inet example_table {
      chain example_chain { # handle 1
        type filter hook input priority filter; policy accept;
        tcp dport ssh accept # handle 4
      }
    }
  2. ルールの代わりに、counter パラメーターを使用してカウンターを追加します。以下の例は、前の手順で表示したルールの代わりに、カウンターを追加します。

    # nft replace rule inet example_table example_chain handle 4 tcp dport 22 counter accept
  3. カウンター値を表示するには、次のコマンドを実行します。

    # nft list ruleset
    table inet example_table {
      chain example_chain {
        type filter hook input priority filter; policy accept;
        tcp dport ssh counter packets 6872 bytes 105448565 accept
      }
    }

21.6.10.3. 既存のルールに一致するパケットの監視

nftables のトレース機能と、nft monitor コマンドを組み合わせることにより、管理者はルールに一致するパケットを表示できます。このルールに一致するパケットを監視するために、ルールのトレースを有効にできます。

前提条件

  • カウンターを追加するルールがある。

手順

  1. チェーンのルール (ハンドルを含む) を表示します。

    # nft --handle list chain inet example_table example_chain
    table inet example_table {
      chain example_chain { # handle 1
        type filter hook input priority filter; policy accept;
        tcp dport ssh accept # handle 4
      }
    }
  2. ルールを置き換えてトレース機能を追加しますが、meta nftrace set 1 パラメーターを使用します。以下の例は、前の手順で表示したルールの代わりに、トレースを有効にします。

    # nft replace rule inet example_table example_chain handle 4 tcp dport 22 meta nftrace set 1 accept
  3. nft monitor コマンドを使用して、トレースを表示します。以下の例は、コマンドの出力をフィルタリングして、inet example_table example_chain が含まれるエントリーのみを表示します。

    # nft monitor | grep "inet example_table example_chain"
    trace id 3c5eb15e inet example_table example_chain packet: iif "enp1s0" ether saddr 52:54:00:17:ff:e4 ether daddr 52:54:00:72:2f:6e ip saddr 192.0.2.1 ip daddr 192.0.2.2 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 49710 ip protocol tcp ip length 60 tcp sport 56728 tcp dport ssh tcp flags == syn tcp window 64240
    trace id 3c5eb15e inet example_table example_chain rule tcp dport ssh nftrace set 1 accept (verdict accept)
    ...
    警告

    nft monitor コマンドは、トレースが有効になっているルールの数と、一致するトラフィックの量に応じて、大量の出力を表示できます。grep などのユーティリティーを使用して出力をフィルタリングします。

21.6.11. nftables ルールセットのバックアップおよび復元

nftables ルールをファイルにバックアップし、後で復元できます。また、管理者はルールが含まれるファイルを使用して、たとえばルールを別のサーバーに転送できます。

21.6.11.1. ファイルへの nftables ルールセットのバックアップ

nft ユーティリティーを使用して、nftables ルールセットをファイルにバックアップできます。

手順

  • nftables ルールのバックアップを作成するには、次のコマンドを実行します。

    • nft list ruleset 形式で生成された形式の場合:

      # nft list ruleset > file.nft
    • JSON 形式の場合は、以下のようになります。

      # nft -j list ruleset > file.json

21.6.11.2. ファイルからの nftables ルールセットの復元

ファイルから nftables ルールセットを復元できます。

手順

  • nftables ルールを復元するには、以下を行います。

    • 復元するファイルが、nft list ruleset が生成した形式であるか、nft コマンドを直接含んでいる場合は、以下のコマンドを実行します。

      # nft -f file.nft
    • 復元するファイルが JSON 形式の場合は、次のコマンドを実行します。

      # nft -j -f file.json

21.6.12. 関連情報