TL

netfilter/nftables:Linux パケット処理パイプライン

iptables のルールがどの順で評価され、どこで NAT が効くのかが地図のように見えてきます。5つのフック点とチェイン走査、nftables での設計刷新、XDP/TC との住み分けまで原理から押さえます。

応用netfilternftablesiptablesファイアウォールXDPカーネル最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.netfilter はネットワークスタックに PREROUTING/INPUT/FORWARD/OUTPUT/POSTROUTING の5つのフック点を持ち、ルーティング判定の前後でパケットを横取りして検査・変換する。チェインはこのフックに登録され、優先度順に評価される。
  • 2.iptables はテーブル(filter/nat/mangle/raw)とチェインが固定で、ルールは線形走査され、IPv4/IPv6 で別実装だった。nftables は単一の仮想マシン(pseudo-state-machine)に統合し、任意のテーブル定義・集合/マップによる定数時間検索・アトミックなルール入れ替えを実現する。
  • 3.XDP は netfilter より手前のドライバ段で動きフックを通る前に超低遅延で落とせる。TC(tc/eBPF)は qdisc 段の整形・分類を担う。netfilter はステートフルな判定と NAT を受け持ち、三者は処理段が異なる補完関係にある。

ネットワークスタックに刺さった「フック点」

Linux のパケットフィルタリングは、独立したミドルウェアではなく ネットワークスタックの内部に埋め込まれたフック(hook) として実装されています。これが netfilter です。IP 層の処理経路には、あらかじめ決められた地点に「コールバックを差し込める穴」が5箇所あり、パケットがその地点を通過するたびに、登録された関数群(チェイン)が呼び出されます。

重要なのは、フック点が ルーティング判定(route lookup)を基準に配置されている ことです。パケットが「自分宛か、転送か」を決める判定の前後でフックが分かれるため、同じパケットでも通るフックが経路によって変わります。この配置を理解すれば、なぜ DNAT は PREROUTING で、SNAT は POSTROUTING でしか効かないのかが必然として腑に落ちます。

                ┌─────────────┐
  受信NIC ─►─ PREROUTING ─► [route?] ─┬─► INPUT ─► ローカルプロセス
                                      │              │
                                  (転送)           ▼(送信)
                                      ▼            OUTPUT
                                   FORWARD ──────────┤
                                      │              │
                                      └─► POSTROUTING ◄┘ ─► 送信NIC

5つのフック点と通過パターン

netfilter のフックは IPv4 では NF_INET_PRE_ROUTINGNF_INET_POST_ROUTING の5つです。パケットの素性によって、この5つのうち決まった組み合わせだけを通ります。

フック点発火タイミング通るパケット
PREROUTING受信直後・route lookup の前受信した全パケット(自分宛・転送問わず)
INPUTroute lookup でローカル宛と判定後このホスト宛のパケット
FORWARDroute lookup で他ホスト宛と判定後転送される(通り抜ける)パケット
OUTPUTローカル生成パケットの送出時このホストが発したパケット
POSTROUTING送出直前・route lookup の後送信する全パケット(転送・ローカル生成問わず)

通過パターンは3種です。受信してローカルで処理 するなら PREROUTING → INPUT転送 なら PREROUTING → FORWARD → POSTROUTINGローカルで生成して送出 するなら OUTPUT → POSTROUTING。転送パケットは INPUT も OUTPUT も通らない点が混乱しやすい急所です。FORWARD が効くのはホストがルータとして振る舞う(IP フォワーディング有効)ときだけです。

NAT の位置が必然である理由

DNAT(宛先変換、典型はポートフォワーディング)は route lookup の 入力に影響する ため、判定より前の PREROUTING で行う必要があります。逆に SNAT/マスカレード(送信元変換)は、どの経路・どの送信元アドレスで出ていくかが確定した でないと変換先を決められないため POSTROUTING で行います。フック点の配置がそのまま「どこで何の NAT ができるか」を規定します。

チェインの評価:優先度とテーブルの正体

各フック点には複数の チェイン を登録でき、チェインには 優先度(priority) という整数が付きます。パケットがフックを通過すると、そのフックに刺さったチェインが優先度の小さい順(負の数が先)に呼ばれます。iptables の「テーブル」(raw/mangle/nat/filter)の正体は、実はこの優先度の違いです。raw が最初(最も小さい優先度)、続いて conntrack によるフロー判定、mangle、nat、最後に filter という順に並んでいるだけで、テーブルは概念的なグループ分けにすぎません。

チェイン内では ルールが上から線形に評価 されます。各ルールはマッチ条件(プロトコル、IP、ポート、インタフェース、接続状態など)とターゲット(ACCEPT/DROP/JUMP など)の組です。条件に合致した最初の終端ターゲットで評価が打ち切られます。接続状態を見るステートフルな判定は conntrack サブシステムが担い、戻りパケットの自動許可などはここに依存します(詳細は Conntrack:ステートフルファイアウォールの内部)。

# iptables:filter テーブルの INPUT チェインを上から評価
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -P INPUT DROP   # どれにも合致しなければ既定ポリシーで落とす

iptables の構造的限界

iptables は長年の標準でしたが、設計上の制約を抱えていました。第一に テーブルとチェインが固定 で、ルール評価が純粋な線形走査である点。ルール数が N 本なら最悪 O(N) の比較が走り、数千ルール規模では評価コストが無視できません。第二に IPv4 と IPv6 が別実装iptablesip6tables)で、さらに ARP 用の arptables、ブリッジ用の ebtables と、プロトコルごとにツールもカーネルコードも分かれていました。

第三が ルール更新の非アトミック性 です。古い iptables は1ルールの追加ごとにテーブル全体をカーネルとやり取りし、大量ルールの一括更新では中間状態が見えたり競合したりしました。第四に、似た条件を多数並べるしかなく(例:100個の IP を許可するなら100ルール)、表現力が乏しいことです。

線形走査は『順序が意味を持つ』ことの裏返し

iptables のルールが上から順に評価されるのは、裏を返せば「先頭で広く ACCEPT してしまうと後段の DROP に到達しない」という順序依存を生みます。ルールが増えるほど評価コストと、順序ミスによる穴の両方が膨らみます。これは iptables の欠陥というより、線形ルールリストという表現形式そのものの限界です。

nftables:単一仮想マシンへの統合

nftables はこれらを根本から作り直しました。核心は、固定のテーブル/チェイン構造をやめ、カーネル内に 汎用のパケット処理仮想マシン(疑似ステートマシン) を置いたことです。ユーザー空間の nft がルールを バイトコードへコンパイル し、カーネルの VM がそれを実行します。これにより設計が次のように変わりました。

観点iptablesnftables
テーブル/チェインfilter/nat 等が固定任意に定義(family・hook・priority を指定)
プロトコルIPv4/IPv6/ARP/bridge で別ツールinet family で IPv4/IPv6 を統合
ルール検索線形走査 O(N)集合(set)/マップ(map)で定数時間に近い検索
更新ルール単位、非アトミックトランザクションで一括・アトミック適用
カーネル実装マッチごとに専用モジュール汎用 VM がバイトコードを実行

最大の実利は 集合(set)とマップ(map) です。iptables なら IP ごとにルールを並べるところを、nftables は集合に対する所属判定1回で済ませます。内部はハッシュや赤黒木で実装され、要素数によらず実質的に定数〜対数時間で引けます。さらに vmap(verdict map) を使えば「キー → 判定」を表として持ち、if-else の連鎖を表引き1回に畳めます。

table inet filter {
  set allowed_v4 { type ipv4_addr; elements = { 10.0.0.0/8, 192.0.2.5 } }

  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    iif "lo" accept
    ip saddr @allowed_v4 tcp dport { 22, 443 } accept   # 集合で一括マッチ
  }
}
hook と priority を自分で書くのが nftables 流

iptables では「filter テーブルの INPUT」のように暗黙だった配置を、nftables では type filter hook input priority 0 のように 明示的に宣言 します。フック点・優先度・family がそのまま文法に現れるため、本記事の前半で見た netfilter の構造(5フック点と優先度順評価)が、ユーザーから直接見えるようになっています。互換のため iptables-nft が iptables 構文を nftables バックエンドへ翻訳する移行経路も用意されています。

XDP・TC との関係:処理段の住み分け

netfilter は強力ですが、パケットが IP スタックに入って conntrack を経た で動きます。より手前で、あるいは別の目的で動く仕組みが XDPTC です。三者は競合ではなく、パイプライン上の 処理段(ステージ)が異なる 補完関係です。

仕組み処理段主用途ステート/NAT
XDPドライバ最早段(skb 生成前)超低遅延のドロップ/リダイレクト(DDoS 緩和、L4LB)原則ステートレス(自前実装は可)
TC (tc/eBPF)qdisc 段(ingress/egress)整形・分類・ポリシング、eBPF での加工限定的(自前なら可)
netfilterIP スタック内の5フック点ステートフルファイアウォール・NATconntrack で完全対応

XDP(eXpress Data Path) は eBPF プログラムを NIC ドライバの受信直後(場合によってはハードウェアオフロード)で走らせ、skb(カーネルのパケット構造体)を生成する に判定します。スタックのオーバーヘッドを丸ごと飛ばせるため、毎秒数千万パケットのドロップやリダイレクトを最小遅延でこなし、DDoS 緩和や L4 ロードバランサに使われます(L4ロードバランサの内部)。代償としてステートフルな判定や NAT は標準では持たず、必要なら自前で組みます。

TC(Traffic Control) は qdisc 層に位置し、本来はキューイングと帯域整形・分類を担当します。ここにも eBPF(tc-bpf)をフックでき、ingress/egress でパケットを加工・分類できます。XDP より後ろ(skb 生成後)ですが netfilter より柔軟な eBPF 加工が可能で、CNI などコンテナネットワークで多用されます。これら高負荷経路でのパケット受信そのものの仕組みは カーネルのパケット受信経路:NAPI と割り込み緩和 を参照してください。

同じ目的を別段で実装すると二重判定になる

XDP/TC/netfilter は段が違うため、同じパケットに対して複数段で判定が走り得ます。例えば XDP で許可したフローを netfilter で再度ステートフル判定するのは正しい構成ですが、整合を取らずに別々のポリシーを置くと、片方を通って片方で落ちる切り分け困難な障害になります。「どの段で何を決めるか」を一貫設計することが前提です。

試験・面接で問われる急所

「netfilter のフック点は」→ PREROUTING/INPUT/FORWARD/OUTPUT/POSTROUTING の5つで route lookup の前後に配置。「DNAT が PREROUTING・SNAT が POSTROUTING な理由」→ DNAT は経路判定の入力、SNAT は出口確定後だから。「iptables テーブルの正体」→ チェイン優先度の違い(raw→mangle→nat→filter)。「nftables の改善点」→ 単一 VM へ統合・set/map で定数時間検索・アトミック更新・inet family で IPv4/6 統合。「XDP/TC/netfilter の違い」→ XDP は最早段で超低遅延ステートレス、TC は qdisc 段の整形・分類、netfilter は conntrack でステートフル判定と NAT。

まとめ

netfilter はネットワークスタックに5つのフック点を埋め込んだ仕組みで、フックは route lookup を基準に配置されるため、通過パターン(受信ローカル・転送・ローカル送出)と NAT の位置(DNAT は PREROUTING、SNAT は POSTROUTING)が構造的に決まります。チェインは優先度順に呼ばれ、iptables のテーブルはその優先度のグループ名にすぎず、ルールは線形走査されます。iptables の固定構造・線形走査・非アトミック更新・プロトコル別実装という限界を、nftables は単一の仮想マシン・集合/マップによる高速検索・トランザクション更新・inet family 統合で作り直しました。そして XDP(ドライバ最早段の超低遅延)と TC(qdisc 段の整形・分類)は netfilter より別の段で動く補完技術であり、どの段で何を決めるかを一貫して設計することが、Linux のパケット処理パイプラインを使いこなす鍵になります。

ネットワーク Article

netfilter/nftables:Linux パケット処理パイプラインを実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

netfilter

比較で見る軸

難易度: advanced / カテゴリ: ネットワーク / タグ数: 6

導入後に効く点

iptables はテーブル(filter/nat/mangle/raw)とチェインが固定で、ルールは線形走査され、IPv4/IPv6 で別実装だった。nftables は単一の仮想マシン(pseudo-state-machine)に統合し、任意のテーブル定義・集合/マップによる定数時間検索・アトミックなルール入れ替えを実現する。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
ネットワーク
タグ数
6

判断チェックリスト

  • 自社の用途が「netfilter / nftables」に近いか確認する。
  • 強みである「netfilter はネットワークスタックに PREROUTING/INPUT/FORWARD/OUTPUT/POSTROUTING の5つのフック点を持ち、ルーティング判定の前後でパケットを横取りして検査・変換する。チェインはこのフックに登録され、優先度順に評価される。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

netfilternftablesiptablesファイアウォールXDPnetfilternftablesiptables
参考: 公式情報