nftables vs iptables

iptables に比べて nftables の利点は何か、移行すべきなのか、という問いについて。

この記事は、現在iptablesで何らかのパケットフィルタリングを実行している人々が、 nftables に移行すべきかを判断する材料になることを意図している。

私は「iptablesに満足していれば、今移行する必要はない」と感じている。もちろん、新規に学習するならば nftables を利用するのもいい。

introduction

本来 nftables と言われるものは、カーネルの nf_tables バックエンドと nftables コマンド(フロントエンド)から成り立っている。

既に多くの新しいディストリビューションは、内部的には nftables (nf_tables) でパケットフィルタリングを実現している。 大抵 iptables コマンドも用意されてはいるが、この場合 iptables コマンドは nf_tables の wrapper として動作している。

逆に言えば、たとえバックエンドが nf_tables に変わっても iptablesコマンドは動作し続ける 。 iptablesコマンドのサポートが落ちるのはまだ先の話だろうから、不満がなければ移行しないという選択肢も出てくる。

従って、「この環境であえて nftables に移行すべきか?」という問いに答えるには、「iptables にない 機能上のメリット が nftables にあるか?」という点を確認したい。

もちろん「nf_tables のパフォーマンス」も重要な点だので、こちらも軽く浚いたい。

feature comparison

私がざっと触れたかぎり、iptablesと比較した nftables の特徴は以下にあると思う。

  • Pros
    • IPv4/IPv6/Ethernetの完全な統合
    • set (ルックアップテーブル)のネイティブ実装
    • 非対話的なスクリプトの読み込みとアトミックな適用
    • JSONのサポート
    • シンプルな設定永続化
  • Cons?
    • 一新されたルール記法

IPv4/IPv6/Ethernetの完全な統合

かつて iptables (IPv4) / ip6tables (IPv6) / ebtables (Ethernet/MAC) に別れていたコマンドは、nft で統合して扱えるようになった。必要であれば1ファイルに全ての設定を記載することもできるし、それらの設定をアトミックに適用することもできる(後述)。

set (ルックアップテーブル)のネイティブ実装

これはiptablesの拡張として実装されていた ipset (iptables-ipset) と同様だ。setとは一組の要素(IPアドレス, MACアドレス, インターフェイスなど)に名前を付けたもので、これを任意のルールから参照することができる。

セットは単に管理上のメリットがあるだけではない。これは登録された要素に対するルックアップテーブルとなるので、 大量の要素に対して高速な判定を行うことができる ことに意味がある。例えば、大量の攻撃者IPアドレスに対するパケットフィルタリングを、スループットを落とさず実行することができる。もしこのフィルタリングをiptablesで1行1要素ずつ作成した場合は、行数に応じて線形的に処理コストが増えていく。

nftables はセットがネイティブに実装された。ipsetと異なり、特に明示的に指定しなくてもハッシュテーブルを利用する形で保存される。

非対話的なスクリプトの読み込みとアトミックな適用

nftablesのルールを安全に更新する で述べたとおり、 nft コマンドはそれ自体がスクリプトエンジンとして動作する。ルールファイルを読み込ませた場合、全てのルールの適用に成功するか、あるいは適用できなければ元のルールのまま、という動作になる。

シンプルな設定永続化

これまでiptablesの設定永続化には、手書きのスクリプトか iptables-persistentが利用されてきた。nftablesの場合、大抵のディストリは永続化を nftables というサービスで実現している。

これはiptables-persistent のように、シャットダウン時に現行の設定を保存するような親切なことはしない。ただサービスの起動・再起動時に /etc/nftables.conf の内容をロードするだけだ。

つまり設定を変更するならば、まず /etc/nftables.conf を修正し、それを systemctl reload nftables で適用するという運用がいいだろう。どうせ設定の適用はアトミックだから、もし記法にエラーがあるなら元通りのままで済むのだ。より安全に設定を適用する方法については nftablesのルールを安全に更新する で述べている。

JSONのサポート

ルールセットの入出力にJSON形式がサポートされた。これは単純に良いことだ。

一新されたルール記法

この点は個人的に良いとも悪いとも言えない。

nftablesのルール記法はiptablesと全く似ていないが、別に平易になったわけでもない。一目で flags interval; の意味を理解できる人なんてまずいないし、 nft -h はひどく貧弱で、スムーズに nft list ruleset に辿り着くことはできない。

nftablesのルール記法の習得には、おおよそiptablesの習得と同じくらいのコストがかかると感じている。逆に言えばさほど困難じゃないのだが、安いコストでもない。

performance comparison

パフォーマンス(スループット)の観点では、以下の2017年の記事が参考になる。もちろん現在の絶対的なパフォーマンス差の参考にはならないが、注意すべきはsetの有無での性能差だ。setが活用されたnftablesとiptables間ではほぼ遜色ないが、特にsetなしでの大量のマッチングでは、nftablesはiptablesよりも明確に低速になっている。

Red Hat Developer: Benchmarking nftables
https://developers.redhat.com/blog/2017/04/11/benchmarking-nftables

ちょっと話が逸れるが、このペンチマーキングにおいて興味深いのは、「iptablesであれnftablesであれ、Dropを指示するテーブルは netdev/prerouting/input のいずれでもパフォーマンスに大差ない」と示された点だ。DDoSに対する防御(パケットフィルタリング)にの観点では、なるべく入力パケット処理の初期段階でDropさせるほうがパフォーマンス上有利ではないかと思うのだが、さほど差はないらしい。

いずれにしてもデータが古いので、近日中に再試を試みたい。

conclusion

先の通り、iptablesコマンドはまだ動作する。iptablesに十分満足していて、上記の特徴にさほどメリットを感じないのなら、今iptablesからnftablesに移行することはないと感じている。