InfraAcademy

InfraAcademy Blog

iptablesはもう本体ではない。firewalld・nftables・iptablesの関係を整理して、Linuxのファイアウォールを迷わず触る

| #Linux #ネットワーク #ファイアウォール
Linuxをブラウザで試してみる

Linux・ネットワーク・AWSを、環境構築なしで実践学習できます

こんにちは、インフラエンジニアのryuです。

新しく構築したサーバーでポートを開けようとして、こんな経験はないでしょうか。

先輩に教わったとおり iptables でルールを足した。iptables -L で見ると、たしかに入っている。それなのに、別の人が nft list ruleset で確認すると、そのルールがどこにも見当たらない。

あるいは、firewall-cmd でポートを開けて疎通も確認できたのに、翌朝サーバーを再起動したら元に戻っていた。

どちらも、よくある事故です。そして原因はだいたい同じところにあります。iptables・nftables・firewalld という3つの名前を、同じ層の話だと思っていることです。

今日は、この3つの関係を整理します。用語の暗記ではなく、目の前のサーバーで自分がどれを触るべきかを判断できるようになるのが目標です。

3つの名前は、そもそも役割が違う

まず、いちばん大事なところから。この3つは「どれを選ぶか」という横並びの選択肢ではありません。

役割を建物にたとえると分かりやすいかもしれません。実際に人を通したり止めたりしているのは、建物の中にある自動ドアです。そのドアを動かす電気信号を送るのが配線、そして受付の人がボタンを押して操作する。この3つを「どれがドアか」と議論しても意味がありませんよね。

同じ構図が、Linuxのファイアウォールにもあります。

名前 役割 どこにいるか
nftables パケットを実際に止める仕組み Linuxカーネルの中
iptables コマンド 昔ながらの書き方を受け付ける入口 ユーザー空間のコマンド
firewalld / ufw ゾーンやサービス名で管理しやすくする道具 さらにその上のデーモン

パケットを止めているのは、カーネルの中のnftables

いまのLinuxで、実際にパケットを通す・落とすという判断をしているのは nftables という仕組みです。

Red Hat のドキュメントでは、nftables は iptables、ip6tables、arptables、ebtables、ipset の後継として位置づけられています。つまり、かつて5つに分かれていた道具が1つに統合された、というのが実態です。

そして RHEL 9 では、iptables のフレームワーク自体が非推奨(deprecated)になりました。これは「まだ動くが、新規に選ぶものではない」という意味です。

Debian でも事情は同じで、Debian 10(Buster)以降は nftables が既定の枠組みになっています。

では、なぜわざわざ作り直されたのでしょうか。理由はいくつかありますが、現場に効くのは次の2点です。

ひとつは、IPv4とIPv6を同じルールで書けるようになったこと。iptables の時代は iptablesip6tables で同じ内容を二重に管理する必要がありました。nftables では inet という family を使って一度に書けます。

もうひとつは、ルールの数が増えても処理が重くなりにくいことです。iptables はルールを上から順に照合していく構造でしたが、nftables はまとまった集合として扱えるため、ルールが数百を超える環境で差が出ます。

iptables コマンドは、いまや翻訳機として動いている

では、いまも iptables コマンドが普通に使えるのはなぜでしょうか。

答えは、多くのディストリビューションで iptables の実体が iptables-nft に差し替えられているからです。これは、iptables の書き方を受け取って nftables のルールに翻訳する互換レイヤーです。

つまり、あなたが iptables -A INPUT ... と打ったとき、コマンドの見た目は昔のままでも、登録されている先は nftables です。

iptables を打っても怒られないのは、後方互換のための翻訳が裏で働いているからであって、iptables という仕組みが現役だからではありません。

この構図を知っておくと、冒頭の「iptables -L では見えるのに nft list ruleset では見つからない」という現象の意味が分かります。見えないのではなく、見ている場所が違うか、そもそも翻訳されていない側に入っているのです。

いちばん上の層にいる firewalld と、ゾーンという考え方

3層目が firewalld です。ここは、下の2つとは目的がはっきり違います。

nftables や iptables がルールを1行ずつ書く道具なのに対して、firewalld は「このインターフェースは外向きだから、HTTPとSSHだけ許可」といった、意味のまとまりで管理するための道具です。

その中心にあるのがゾーンです。firewalld は、ネットワークインターフェースや接続元アドレスを publicinternaltrusted といったゾーンに振り分け、ゾーンごとに許可する内容を決めます。

ここでつまずきやすいのが、ポートを開けたつもりが、そのサーバーが実際に使っているゾーンとは別のゾーンに対して設定していた、というパターンです。設定は入っているのに効かない、という状態になります。

firewall-cmd --get-active-zones   # どのインターフェースがどのゾーンか
firewall-cmd --get-default-zone   # ゾーン指定を省いたときの行き先

firewall-cmd でゾーンを指定しなかった場合は、既定ゾーンに設定が入ります。複数のNICを持つサーバーでは、まずこの2つを確認してから作業してください。

自分のサーバーがどれで動いているか、先に確かめる

設定を触る前に、必ず現状を確認します。これを飛ばすと、あとで原因の分からない不通を生みます。

確認は3つだけです。どのコマンドが入っているか、どの実体が使われているか、そして誰がルールを管理しているか。

# 1) iptables の実体がどちらか(カッコの中が重要)
iptables -V
#   iptables v1.8.10 (nf_tables)   ← 翻訳レイヤー経由
#   iptables v1.8.10 (legacy)      ← 昔ながらの仕組み

# 2) nftables 側から全体を見る(翻訳されたルールもここに出る)
sudo nft list ruleset

# 3) 管理デーモンが動いていないか
systemctl is-active firewalld ufw nftables iptables 2>/dev/null

iptables -V の末尾に (nf_tables) と出ていれば、そのサーバーの iptables は翻訳機です。(legacy) と出たなら、本当に古い仕組みを直接触っています。

nft list ruleset を、まず一度は通しで眺める

nft list ruleset は、カーネルに入っているルールを丸ごと表示します。少し読みにくいのですが、全体像がここに集約されるので、切り分けの起点として優秀です。

翻訳レイヤー経由で入ったルールは、table ip filter のような互換用のテーブルとして現れます。firewalld が作ったルールは table inet firewalld のように、名前で見分けがつきます。

出力が長くて追いきれないときは、テーブルの一覧だけを先に見ると全体がつかめます。

sudo nft list tables          # どんなテーブルがあるか
sudo nft list table inet firewalld   # firewalld のルールだけを見る

管理している「主」が誰なのかを確定させる

もうひとつ大事なのが、ルールを管理しているのが誰かという点です。

firewalld や ufw が動いている環境では、これらのデーモンが自分の管理下のルールを定期的に作り直します。そこへ手で iptables からルールを足しても、リロードのタイミングで消えます。

デーモンの状態確認は systemd を使うので、サービスが思ったとおりに動いていないときの読み方は設定を直して再起動したのに、何も変わらない。systemdの言い分をsystemctlとjournalctlで読み解くがそのまま役に立ちます。

現場で踏みやすい3つの地雷

ここからは、実際にトラブルになりやすいパターンです。どれも一度は見たことがあるのではないでしょうか。

legacy と nft が混ざって、ルールが半分見えなくなる

いちばん厄介なのがこれです。

Debian 系では update-alternativesiptables の実体を iptables-nftiptables-legacy のどちらにも切り替えられます。便利な仕組みなのですが、切り替えた前後でルールを入れると、2つの置き場所に分かれて残ります。

# Debian 系で、いまどちらが選ばれているかを見る
update-alternatives --display iptables

# legacy 側に取り残されたルールが無いか確認する
sudo iptables-legacy -S
sudo iptables-nft -S

iptables-legacy -S に何か出てきたら要注意です。そのルールは nftables 側からは見えず、しかしカーネルでは有効なままなので、「設定を全部消したはずなのに通信が落ちる」という状態を作ります。

Docker や Kubernetes を動かしているサーバーでは、コンテナ側が自動でルールを注入するため、この混在が起きやすくなります。手で消してもすぐ戻される場合は、注入している主がいないかを疑ってください。

こうした環境で気をつけたいのが、コンテナ基盤が起動した時点の実体と、あとから人が切り替えた実体がずれる場合です。デーモンが legacy 側でルールを作り、人が nft 側を見ている。同じサーバーの中に、お互いを知らない2冊の台帳ができているような状態です。

対処の方針としては、どちらかに寄せたうえで、コンテナ基盤のサービスを再起動してルールを作り直させるのが確実です。片方を消して回るより、はるかに早く片付きます。

firewalld が動いているのに、iptables で直接足してしまう

2つめは、管理の二重化です。

firewalld を使う環境では、ルールの追加は firewall-cmd に統一します。iptables から足したものは、firewalld のリロードや再起動で上書きされて消えます。

やっかいなのは、消えるまでに時間差があることです。追加した直後は通信が通るので、作業した本人は成功したと思って帰ります。異変に気づくのは、数日後に誰かがリロードしたときです。

このとき困るのが、原因の特定が難しくなることでしょう。設定した記録も残っていなければ、「なぜか急につながらなくなった」という報告だけが残ります。

なお RHEL 9 では、firewalld の iptables バックエンドと、独自ルールを流し込む --direct オプションも非推奨になりました。RHEL 8.10 および 9.4 以降は、firewalld のバックエンドが既定で nftables になっています。逃げ道として --direct を使う書き方は、もう将来性がありません。

どうしても firewalld の語彙で表現できないルールが必要なら、firewalld を止めて nftables を直接管理するか、firewalld のリッチルールで書き切るかの二択で考えたほうが、あとあと楽です。

--permanent を忘れて、再起動で設定が消える

3つめは、いちばん頻繁に起きるやつです。

firewall-cmd の設定には、いま動いている状態(runtime)と、保存された状態(permanent)の2つがあります。--permanent を付けずに実行した変更は、runtime にしか入りません。

# よくある間違い:いまは効くが、再起動やリロードで消える
sudo firewall-cmd --add-port=8080/tcp

# 正しい手順:保存してから読み込む
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

# もう runtime だけで作業してしまった場合の救済
sudo firewall-cmd --runtime-to-permanent

ここで注意したいのが --reload の挙動です。--reload は、保存された内容で runtime を置き換えます。ですから、--permanent を付けずに追加したルールがある状態で --reload を打つと、その場で消えます。

「疎通確認は通ったのに、リロードしたら落ちた」という事故は、たいていこれです。作業後は次の2つを見比べる癖をつけておくと安心です。

sudo firewall-cmd --list-all               # いま効いている内容
sudo firewall-cmd --permanent --list-all   # 保存されている内容

結局、いまどれを触ればいいのか

整理すると、判断は環境で決まります。悩む場面が減るように、表にまとめておきます。

環境 触るもの 避けること
RHEL / Rocky / AlmaLinux(firewalld あり) firewall-cmd に統一 iptables で直接追加、--direct の新規利用
Ubuntu(ufw あり) ufw に統一 ufw と iptables の併用
管理デーモンを入れていない nft でルールセットを管理 iptables 構文での新規作成
既存の iptables 資産がある まずは動かし、移行計画を別に立てる legacy と nft の混在を放置する

新しく作るサーバーなら、iptables 構文で書き始める理由はもうありません。既存のルールが大量にある場合は、慌てて書き換えるより、iptables-translate などで少しずつ nftables 構文に寄せていくほうが安全です。

移行のときに忘れがちなのが、作業中に自分が締め出される可能性です。リモートからSSHでつないで作業している以上、途中でSSHのポートを落とすルールが入れば、その瞬間に手が届かなくなります。

コンソールから入れる環境なら慌てずに済みますが、そうでないなら、一定時間で元に戻す仕掛けを用意しておくと安心です。変更を適用したあと、決めた時間内に自分で止めなければ設定が巻き戻る、という形にしておく方法がよく使われます。

そして、ファイアウォールは単体では判断できません。クラウドであればセキュリティグループなど手前の制御もありますし、そもそもパケットが届いていない可能性もあります。

通信が通らないときの切り分け全体の順番はその通信、どこで止まっていますか? ping・ss・tcpdumpで疎通トラブルを層ごとに切り分けるにまとめてあります。OS側の設定を疑う前に、そちらの順番で層を絞り込んでから来ると、確認する範囲がぐっと狭くなります。

クラウド側の制御と組み合わせて考えたい場合は、AWSのEC2とは何かもあわせて読むと、どこで止まっているのかの見当をつけやすくなります。

なお、この手のコマンドは基本的に管理者権限が必要です。sudo の扱いに不安があれば、Linuxのsudoコマンドの使い方を先に押さえておくとよいでしょう。

パケットの流れやアドレスの考え方から体系的に学び直したいという方には、InfraAcademy のネットワークの学習ロードマップが順番どおりに並んでいます。ファイアウォールの設定でつまずく原因の多くは、コマンドの知識ではなく、どこで何が起きているかの地図が無いことなので、遠回りに見えて近道です。

まとめ

最後に要点を振り返ります。

nftables はカーネルの中でパケットを止める仕組み、iptables コマンドは昔の書き方を翻訳する入口、firewalld や ufw はその上で管理しやすくする道具です。3つは並列の選択肢ではなく、層が違います。

作業を始める前に iptables -V のカッコの中と nft list ruleset、そして管理デーモンの稼働状態を確認します。ここで現状を確定させておけば、あとの判断に迷いません。

そして、ルールを管理する主はひとつに決めることです。firewalld が動いているなら firewall-cmd に、入れていないなら nft に統一します。混ぜた瞬間に、見えないルールが生まれます。

この3つはどれも古い知識ではなく、いまも現場で同時に目にするものです。だからこそ、名前を覚えるより関係を覚えたほうが応用が利きます。初めて入るサーバーでも、層の地図さえ頭にあれば「いまどこを見ているのか」を見失いません。

3つの関係さえ頭に入っていれば、初めて触るサーバーでも落ち着いて手順を組み立てられます。次にポートを開けるときは、まず iptables -V から始めてみてください。

参考記事

Next Action

記事で読んだ内容を、講座で実装してみましょう

InfraAcademyでは、ブラウザ上でLinuxやネットワークの実践環境を使いながら学習できます。無料で始められる講座から、学習の流れを試せます。

この記事を書いた人

ryu

InfraAcademy運営 / エンジニア

エンジニア歴10年。Linux、ネットワーク、クラウドを中心に、実務で役立つインフラ技術を初心者にもわかりやすく解説しています。

X: @ryu63614894

Related

関連記事

ブログ一覧へ

Roadmap

まずはこの4講座から

ログインすれば無料で始められる講座です。気になったテーマから手を動かして学べます。

講座一覧を見る