Linuxにおけるnftablesのインストールと設定ガイド:iptablesを完全移行する

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

クイックスタート:5分で構築するnftables基本ファイアウォール

かつてのLinuxにおけるファイアウォール管理は、IPv4用のiptablesとIPv6用のip6tablesという2つの独立したルールセットを維持しなければならず、運用の負担となっていました。nftablesの登場により、Linuxはこれらを単一のフレームワークへと統合しました。より直感的な構文、ダウンタイムのないアトミックなルール更新、そして大幅に向上したパケット処理パフォーマンスを実現できます。

ステップ 1: インストールと既存ファイアウォールの停止

nftablesを有効化する前に、Linuxカーネル内でのフックの競合を回避するため、上位レイヤーのファイアウォールサービスを停止します。

# Ubuntu / Debian の場合
sudo apt update && sudo apt install -y nftables
sudo systemctl stop ufw && sudo systemctl disable ufw

# RHEL / AlmaLinux / Rocky Linux の場合
sudo dnf install -y nftables
sudo systemctl stop firewalld && sudo systemctl disable firewalld

ステップ 2: サーバー保護のための最小限のルールセットを読み込む

デフォルトの設定ファイルは /etc/nftables.conf に配置されています。エディタでファイルを開きます。

sudo nano /etc/nftables.conf

既存の内容を削除し、以下の標準ルールセットを貼り付けます。この設定により、既存のSSH接続を維持しつつWebポートを開放し、その他の不正なトラフィックをすべて遮断します。

#!/usr/sbin/nft -f

flush ruleset

table inet my_firewall {
    chain my_input {
        type filter hook input priority filter; policy drop;

        # 内部ループバックを許可
        iif "lo" accept

        # 確立済みの接続を維持(既存のSSHセッション切断を防止)
        ct state established,related accept
        ct state invalid drop

        # IPv4およびIPv6のICMP pingを許可
        ip protocol icmp accept
        ip6 nexthdr ipv6-icmp accept

        # サービスポートの開放: SSH (22)、HTTP (80)、HTTPS (443)
        tcp dport 22 accept
        tcp dport { 80, 443 } accept
    }
}

ステップ 3: 構文チェックとサービスの有効化

すぐにサービスを再起動しないでください。設定ファイル内のわずかなタイポ(タイプミス)でも、リモートSSH接続から恒久的に締め出される恐れがあります。

# 1. ルールを適用せずに構文エラーを検証(dry-run)
sudo nft -c -f /etc/nftables.conf

# 2. サービスの起動およびOS起動時の自動実行を有効化
sudo systemctl enable --now nftables

# 3. カーネル内でアクティブなルールセットを確認
sudo nft list ruleset

単一の inet テーブルを定義するだけで、ルールを二重に記述することなく、両方のネットワークプロトコルを完全に保護できます。

nftablesのコアアーキテクチャと基本構文

nftablesのモデルは、Table → Chain → Rule という明確な階層構造で構成されています。

1. Tableとアドレスファミリ

nftablesには filter や nat のような暗黙の定義済みテーブルは存在しません。管理者が明示的にテーブルを作成し、適切なアドレスファミリを割り当てます。

  • inet: 同一テーブル内でIPv4とIPv6の混在処理をサポート。インターネット公開サーバーの大部分において最適な選択肢です。
  • ip / ip6: IPv4またはIPv6パケットのみを個別に処理します。
  • netdev: ingress フックをサポートし、TCP/IPスタックに到達する前のネットワークドライバ段階で不要パケットのフィルタリングやドロップが可能なため、DDoS対策に極めて有効です。
  • bridge / arp: L2スイッチングやMACアドレス解決テーブルの処理に使用されます。

2. レギュラーチェインとベースチェインの違い

チェインはパケット処理ルールをグループ化する場所です。nftablesでは2種類が明確に区別されています。

  • Base chain(ベースチェイン): hook キーワード(input、output、forward など)を介してLinuxカーネルのネットワークスタックに直接フックします。このタイプのチェインには、priority(実行優先度)とデフォルトの policy(accept または drop)の定義が必須です。
  • Regular chain(レギュラーチェイン): システムフックを持ちません。他のルールからジャンプ(jump)して呼び出されるサブルーチンのように機能し、複雑な設定のモジュール化に役立ちます。

3. ルール構文:左から右へ自然に読める構成

nftablesの構文では、iptables特有の覚えにくい略記パラメータが排除されています。ルールは [一致条件] [アクション] という直感的な構造で記述します。

# 単一行で複数のポートリストにマッチ
tcp dport { 80, 443, 8080, 8443 } accept

# ICMPフラッド対策としてpingの受信レートを制限
ip protocol icmp limit rate 5/second accept

高度な実践テクニック:NAT、ポートフォワーディング、ブルートフォース対策

カーネルのIPフォワーディングの有効化

NATやポートフォワーディングを設定する前に、Linuxカーネルのパケット転送機能を有効化しておく必要があります。

sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.d/99-ipforward.conf

1. 送信元NAT(マスカレード)の設定

Linuxサーバーをゲートウェイとして構築し、ローカルLANや内部コンテナ向けにインターネット接続を共有する場合に適用します。

table ip nat_gateway {
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        oifname "eth0" masquerade
    }
}

2. ポートフォワーディング(DNAT)

パブリックIP宛てのトラフィックを内部のアプリケーションサーバーへ転送します(例: eth0 インターフェースのポート8080宛てをサーバー 192.168.10.50 のポート80へ転送)。

table ip nat_gateway {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        iifname "eth0" tcp dport 8080 dnat to 192.168.10.50:80
    }
}

3. Dynamic Setを活用したSSHブルートフォース攻撃の自動遮断

Fail2banのようなメモリ消費の大きいデーモンを導入する代わりに、nftablesの meter と動的 set 機能を使用することで、攻撃元IPをカーネルレイヤーで直接隔離できます。

table inet my_firewall {
    # 違反IPを自動記録するブラックリスト(15分後に期限切れ)
    set ssh_blacklist {
        type ipv4_addr
        flags dynamic, timeout
        timeout 15m
    }

    chain my_input {
        type filter hook input priority filter; policy drop;

        iif "lo" accept
        ct state established,related accept

        # ブラックリストに登録されているIPからの通信を即時ドロップ
        ip saddr @ssh_blacklist drop

        # 1分間に4回を超える新規SSH接続を試行したIPを記録し、自動的にブラックリストへ追加
        tcp dport 22 ct state new meter ssh_meter { ip saddr limit rate over 4/minute } add @ssh_blacklist { ip saddr } drop
        
        # 通常の正当な新規SSH接続を許可
        tcp dport 22 ct state new accept
    }
}

本番運用における実践ノウハウ

パフォーマンス比較:O(1) と O(n)

秒間約40,000リクエストを処理するマイクロサービス環境において、iptables で3,000件以上のIPブラックリストを運用していた際、各コアの ksoftirqd CPU使用率が25%まで跳ね上がる事象が発生しました。これは、iptablesがルールを上から順に1行ずつ線形探索(計算量 O(n))するためです。

nftables に移行し、IPアドレス群を Set 構造(カーネル内ではハッシュテーブルまたは赤黒木として実装)にまとめたところ、検索時間は O(1) に短縮されました。softirqによるCPU専有率は25%から2%未満へと劇的に減少し、ネットワーク遅延の安定化が顕著に確認できました。

iptablesからnftablesへの自動変換

サーバー上にすでに数百行に及ぶ複雑なiptablesルールが存在する場合でも、手動で再入力する必要はありません。

# 1. 現在のルールセットをファイルへエクスポート
sudo iptables-save > iptables_backup.rules

# 2. 自動変換ツールを使ってnftables構文へ変換
sudo iptables-restore-translate -f iptables_backup.rules > rules_converted.nft

# 3. 変換後の内容を確認
cat rules_converted.nft

リモートSSHアクセス喪失(ロックアウト)の防止策

リモートサーバー上でファイアウォールを変更する際は、誤設定による締め出しを防ぐため、自動復旧メカニズムを用意しておくことが鉄則です。

# 5分後にルールセットを自動クリアするコマンドをバックグラウンドで実行
sleep 300 && sudo nft flush ruleset &

ルールの再読み込み後もSSH接続が維持されていることを確認できたら、kill %1 を実行してsleepプロセスを破棄します。万が一締め出された場合でも、5分経過すれば自動的にルールが全消去され、通常通り再アクセスが可能になります。

Share: