Linuxでのnftables完全マスター:iptablesを置き換える最新ステートフルファイアウォールの構築

Security tutorial - IT technology blog
Security tutorial - IT technology blog

アプローチの比較:iptablesとnftablesのアーキテクチャ

半年ほど前、当チームは450台以上のLinuxノード全体でレガシーなiptablesの運用を廃止しました。毎秒80,000リクエスト以上を処理する高スループットなAPIゲートウェイを運用する中で、従来のNetfilterツールの限界に直面したためです。

従来のiptablesでは、すべてのパケットがあらかじめ固定定義されたテーブル(filter、nat、mangle、raw)のパイプラインを通過します。さらに厄介なことに、IPv4(iptables)、IPv6(ip6tables)、ARP(arptables)、ブリッジング(ebtables)がそれぞれ独立したルールツリーを持つ別々のCLIツールとして動作していました。高トラフィック負荷のもとで、これら個別のレイヤーにまたがる数百ものルールを順次評価していくと、CPUオーバーヘッドは急激に上昇します。

nftablesフレームワークはこの設計上の欠陥を解消します。カーネル内のコンパクトなバイトコード仮想マシンを中心に構築されており、フィルタリングの仕組みを根本から変革しています。

  • 統合されたアドレスファミリ:inetファミリにより、IPv4とIPv6のトラフィックを単一の共通ルールセットで処理できます。両方のIPバージョンのために重複したファイアウォールファイルを管理する必要はもうありません。
  • カスタムチェーンとテーブル:カーネルテーブルはデフォルトでハードコードされなくなりました。ワークロードで実際に使用する特定のフックのみを作成・実行します。
  • アトミックなルールセットの読み込み:従来のツールはルールを1行ずつフラッシュして追加するため、トラフィックがポリシーをすり抜けたり処理が滞ったりする一時的な空白期間が生じていました。対照的に、nftablesは設定ファイル全体をカーネルの単一アトミックトランザクションとして適用します。
  • セットベースのルックアップ:50個のポートルールを1つずつ線形に評価するのではなく、nftablesは内部ハッシュテーブルを使用します。セットのサイズに関係なく、ルックアップは一定のO(1)または対数O(log n)の時間で実行されます。

本番運用6ヶ月で分かったメリットとデメリット

nftablesを大規模環境で運用したことで、パフォーマンスの向上と運用のハードルの両面について具体的なデータが得られました。

主なメリット

  • 可読性の高い構文:-A INPUT -p tcp -m multiport --dportsのようなシェルフラグの長くて分かりにくい文字列ではなく、クリーンなプログラミング構文のようにルールを記述できます。
  • 測定可能な効率性:ゲートウェイクラスター全体において、セットベースのルックアップへ切り替えたことで、ピーク時の接続スパイクにおけるsoftirq CPU使用率が約18%削減されました。
  • 瞬時かつ安全なリロード:最も高負荷なノードでも、nft -f /etc/nftables.confを実行すれば40ミリ秒未満でルールがリロードされます。タイポがあった場合でも、パーサーが実行中のカーネル状態に手を加える前に処理を中断するため、更新の途中でアクティブなファイアウォールが壊れる心配はありません。

トレードオフと課題

  • ツールの移行ラグ:一部の古いデプロイスクリプトやコンテナランタイムは、依然としてレガシールールを直接挿入します。競合を避けるため、移行中はiptables-nft翻訳レイヤーを維持しなければならないケースがよくあります。
  • 学習コストの高さ:テーブルがあらかじめ用意されていないため、エンジニアはprerouting、input、forward、output、postroutingといった正確なNetfilterフックとその実行優先順位を理解しておく必要があります。

最新サーバーを保護するための推奨構成

単体のアプリケーションサーバーやクラウドインスタンスには、厳格なステートフルベースラインが最も効果的な防御となります。確立されたTCPおよびUDPセッションを自動的に追跡し、不正なパケットや順序の狂ったパケットはWebデーモンに到達する前に破棄されます。

ネットワーク境界を固める前に、まずはシステムアクセスを保護しましょう。新規のUbuntuやAlmaLinuxインスタンスを立ち上げる際は、最初に強固で固有の認証情報を生成してください。筆者は普段、toolcraft.app/ja/tools/security/password-generatorのクライアントサイドジェネレーターを活用しています。キーをネットワーク上に送信することなく、ブラウザ上でエントロピーの高いパスワードを直接作成できます。SSHキーとパスワードの準備が整ったら、以下のファイアウォールルールセットを展開します。

ベースラインブループリント

本番ベースラインは、以下の5つのコアポリシーに基づいています。

  1. ループバックインターフェース(lo)上のすべての双方向トラフィックを許可する。
  2. アクティブな接続を維持するため、すべてのestablished(確立済み)およびrelated(関連)パケットを許可する。
  3. カーネルのconntrackテーブルによってinvalid(無効)と判定されたパケットを即座に破棄する。
  4. 特定の受信ポート(SSH、HTTP、HTTPS)を許可しつつ、新規ハンドシェイクにレート制限を適用してブルートフォース攻撃を抑止する。
  5. inputおよびforwardチェーンのデフォルトポリシーを、その他すべてのパケットを破棄(drop)するように設定する。

実装ガイド:nftablesのステップ別デプロイ手順

1. nftablesのインストールとレガシールールのクリーンアップ

最新のDebian、Ubuntu、AlmaLinux、Rocky Linuxシステムにネイティブのユーザースペースユーティリティをインストールします。UFWやFirewalldなどの競合するファイアウォールラッパーは無効化してください。

# Ubuntu/Debianの場合
sudo apt update && sudo apt install -y nftables
sudo systemctl stop ufw 2>/dev/null || true
sudo systemctl disable ufw 2>/dev/null || true

# RHEL/AlmaLinux/Rocky Linuxの場合
sudo dnf install -y nftables
sudo systemctl stop firewalld 2>/dev/null || true
sudo systemctl disable firewalld 2>/dev/null || true

2. アトミックな設定ファイルの作成

ルールを/etc/nftables.confに直接記述します。以下の設定により、IPv4/IPv6のデュアルスタック保護、レート制限付きSSH、Webトラフィックの許可、必須ICMPタイプの適切な処理が実現します。

#!/usr/sbin/nft -f

# 既存のルールセットをフラッシュ
flush ruleset

# デュアルスタック対応のinetテーブルを定義
table inet server_firewall {

    # 動的なポート管理用の名前付きセット
    set allowed_tcp_ports {
        type inet_service
        flags interval
        elements = { 22, 80, 443 }
    }

    chain input {
        # 標準のfilterプライオリティでNetfilterのinputパイプラインにフック
        type filter hook input priority filter; policy drop;

        # 1. ローカルループバックトラフィックを許可
        iifname "lo" accept

        # 2. ステートフルインスペクション:確立済み・関連接続を許可し、無効パケットを破棄
        ct state established,related accept
        ct state invalid drop

        # 3. ICMP / ICMPv6を許可(Path MTU Discoveryやネットワーク診断に必須)
        ip protocol icmp icmp type { echo-request, destination-unreachable, time-exceeded } accept
        ip6 nexthdr icmpv6 icmpv6 type { echo-request, destination-unreachable, packet-too-big, time-exceeded, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept

        # 4. SSHブルートフォース対策(IPごとの新規接続を毎分10回までに制限)
        tcp dport 22 ct state new meter ssh-meter { ip saddr limit rate over 10/minute burst 5 packets } drop

        # 5. セットで定義された許可ポートへの受信トラフィックを許可
        tcp dport @allowed_tcp_ports accept

        # 6. それ以外のトラフィックを正常に拒否
        meta l4proto tcp reject with tcp reset
        reject with icmpx type port-unreachable
    }

    chain forward {
        # ルーター以外のホストでは転送パケットをすべて破棄
        type filter hook forward priority filter; policy drop;
    }

    chain output {
        # ホストからの全送信接続を許可
        type filter hook output priority filter; policy accept;
    }
}

3. ルールの検証とアトミックな適用

ファイアウォールの更新をカーネルに適用する前に、必ず構文を検証してください。-cチェックフラグを使用すると、設定を適用せずに構文チェックのみを行えます。

# 構文チェック
sudo nft -c -f /etc/nftables.conf

# ルールをアトミックに適用
sudo nft -f /etc/nftables.conf

4. 稼働状況の確認とトラフィックのモニタリング

以下の2つのコマンドを使用して、実行中のテーブル定義やセットのカウンターを確認したり、パケット破棄のログをリアルタイムでストリーミング監視したりできます。

# 現在稼働中の設定全体を表示
sudo nft list ruleset

# パケットがdrop/rejectフックにヒットしたイベントをリアルタイム監視
sudo nft monitor

5. Systemdによる永続化の有効化

システム起動時にルールセットが自動的にロードされるよう、nftablesデーモンを設定します。

sudo systemctl enable nftables
sudo systemctl restart nftables
sudo systemctl status nftables

nftablesへ移行することで、ホストセキュリティを単一の洗練されたフレームワークへ統合できます。デュアルスタックの統一処理、アトミックなリロード、O(1)のセットパフォーマンスを備えたnftablesは、Linuxシステムに高速で極めて信頼性の高い防御基盤を提供します。

Share: