- Published on
Linuxファイアウォールとアクセス制御完全ガイド: nftables、firewalld、ufwを締め出されずに扱う
- Authors

- Name
- Youngju Kim
- @fjvbn20031
- はじめに
- 1. 自分自身を締め出さないための手順
- 2. nftablesの構造 — テーブル、チェイン、ルール
- 3. nftablesの照会と修正
- 4. firewalld — ゾーンベースの管理
- 5. ufw — 単純さが必要な場所
- 6. ルールが適用されないとき — 診断順序
- 7. アクセス制御の残りの階層
- クイズ: 理解度を確認しましょう
- おわりに
- 参考資料
- 関連記事
はじめに
ファイアウォール作業の本当の危険は、ルールを書き間違えることではありません。リモートでルールを適用した瞬間に自分自身が遮断され、元に戻す手段がなくなることです。データセンターへ行けず、コンソールへのアクセス手段もないなら、そのサーバーは事実上失われたことになります。
そこでこの記事は、ルールの文法よりも手順を前面に置きます。何をどの順序で適用し、失敗したときにどうやって自動的に元へ戻すのかが核心です。文法はその次です。
扱う範囲は三つの階層です。カーネルのnetfilterの上にnftablesがあり、その上にfirewalldやufwのような管理ツールがあります。どのツールを使っても、最終的には同じカーネルフックにルールが入るという点を理解すれば、ツール間の移動が容易になります。
前提はnftables 1.0以上、firewalld 1.x、ufw 0.36以上です。RHEL系の8以上はfirewalldが既定で、バックエンドはnftablesです。Debian系やUbuntuではufwが慣例であり、こちらも同様にnftablesの上で動作します。iptablesコマンドが残っているディストリビューションでも、たいていはnftablesへ変換して処理する互換レイヤーです。
1. 自分自身を締め出さないための手順
技術的な内容に入る前に、この手順を先に体へ覚え込ませてください。順序がすべてです。
手順1 — 巻き戻しの予約を先に入れます。 ルールを適用する前に「一定時間後に自動で復旧」を予約しておきます。接続が切れれば予約が生き、元の状態へ戻ります。
# nftables: 現在の状態を保存し、10分後の自動復旧を予約
sudo nft list ruleset > /root/nft-backup-2026-08-15.nft
echo "nft -f /root/nft-backup-2026-08-15.nft" | sudo at now + 10 minutes
at がない環境なら、バックグラウンドのシェルでも同じことができます。
sudo setsid bash -c 'sleep 600; nft -f /root/nft-backup-2026-08-15.nft' >/dev/null 2>&1 &
手順2 — 検証してから適用します。 nftablesはファイル全体の文法検査だけを行えます。
sudo nft -c -f /etc/nftables/main.nft
-c はドキュメントによれば適用せずに妥当性のみを確認します。必ず通してください。
手順3 — 接続を確認します。 既存のセッションを閉じずに、新しいターミナルから接続してみます。
手順4 — 確認が終わったら予約を取り消し、恒久保存します。
atq
sudo atrm 3
sudo systemctl enable --now nftables
firewalldにはこの手順が機能として組み込まれています。--timeout を指定すると、指定時間の後にルールが自動的に消えます。
sudo firewall-cmd --zone=public --add-port=8080/tcp --timeout=5m
ドキュメントによれば、--timeout は --permanent と併用できません。ランタイムのルールにのみ適用されるからです。この組み合わせは、firewalldを使う実務上もっとも大きな理由の一つです。
緊急時用のコマンドも知っておいてください。
sudo firewall-cmd --panic-on
sudo firewall-cmd --panic-off
--panic-on はドキュメントの表現どおり、受信・送信のすべてのパケットを破棄します。侵害対応の際に即座に隔離する用途であり、リモートで実行すればその瞬間に接続が切れます。コンソールアクセスが確保された状態でのみ使ってください。
2. nftablesの構造 — テーブル、チェイン、ルール
nftablesは三つの階層で構成されます。
- テーブル: アドレスファミリーごとのコンテナです。ファミリーは
ip、ip6、inet、arp、bridge、netdevです。inetはIPv4とIPv6をまとめて処理するため、多くの場合はこれを使います。 - チェイン: ルールの束です。カーネルフックに付くベースチェインと、ジャンプによってのみ到達する通常チェインがあります。
- ルール: マッチ条件と判定(verdict)の組み合わせです。
ベースチェインの宣言には、タイプ、フック、優先度が必要です。
sudo nft add table inet filter
sudo nft add chain inet filter input '{ type filter hook input priority filter; policy drop; }'
sudo nft add chain inet filter forward '{ type filter hook forward priority filter; policy drop; }'
sudo nft add chain inet filter output '{ type filter hook output priority filter; policy accept; }'
フック名は prerouting、input、forward、output、postrouting、ingress、egress です。優先度はキーワードで指定でき、ドキュメント基準の値は raw(-300)、mangle(-150)、dstnat(-100)、filter(0)、security(50)、srcnat(100)です。
既定ポリシーは accept(既定値)または drop です。policy drop を宣言した瞬間、そのフックへ入ってくるすべてのパケットが遮断されるため、必ず許可ルールを先に入れてからポリシーを変更する順序を守る必要があります。
ルールの追加は次のとおりです。
sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter input iif lo accept
sudo nft add rule inet filter input tcp dport 22 accept
sudo nft add rule inet filter input ip saddr 10.0.0.0/8 tcp dport 5432 accept
sudo nft add rule inet filter input ip protocol icmp accept
ct state established,related acceptはもっとも先に来るべきルールです。すでに成立した接続の応答パケットを許可します。これがないと、サーバーが外へ送った要求の応答まで遮断されます。iif lo acceptはループバックを許可します。これが抜けるとローカルサービス間の通信が切れ、原因を突き止めにくい障害になります。- 判定は
accept、drop、reject、jump、gotoです。
drop と reject の違いを知っておいてください。drop は応答なしで破棄するため、クライアントはタイムアウトまで待ちます。reject は拒否応答を返すので即座に失敗します。外部公開ポートにはスキャン対策上 drop が、内部網では診断の都合上 reject がよく選ばれます。
この選択が運用に与える影響は、思いのほか大きいです。内部サービス間の通信を drop で遮断すると、呼び出す側は接続タイムアウトまでスレッドを掴んだまま待ちます。タイムアウトが30秒に設定されていれば、その間にコネクションプールが枯渇し、結局ファイアウォールのルール一つがサービス全体の遅延へ波及します。内部網では速く失敗するほうがよいという原則を覚えておいてください。
アドレスとポートを集合(set)にまとめると、ルールがはるかに簡潔になります。集合は別に定義して複数のルールから再利用でき、内容だけを更新すればルールに触れずに許可対象を変更できます。
sudo nft add set inet filter admin_ips '{ type ipv4_addr; flags interval; }'
sudo nft add element inet filter admin_ips '{ 10.0.3.0/24, 10.0.9.7 }'
sudo nft add rule inet filter input ip saddr @admin_ips tcp dport 22 accept
sudo nft list set inet filter admin_ips
flags interval は帯域表記を許可します。管理者IPの一覧が変わったときにルールではなく集合だけを更新すればよいので、運用ミスが減ります。
3. nftablesの照会と修正
sudo nft list ruleset
sudo nft list table inet filter
sudo nft -a list ruleset
sudo nft list chain inet filter input
-a は各ルールにハンドル番号を付けて表示します。削除はハンドルによってのみ正確に指定できるため、このオプションは必須です。
sudo nft -a list chain inet filter input
sudo nft delete rule inet filter input handle 5
sudo nft insert rule inet filter input position 4 tcp dport 443 accept
add はチェインの末尾に、insert は先頭または指定位置に入れます。ルールは上から下へ評価され、最初のマッチで判定が決まるため、順序が結果を変えます。
全体の初期化は次のとおりです。
sudo nft flush ruleset
破壊的コマンドの警告: ドキュメントが明示するとおり、nft flush ruleset はすべてのテーブルとその内容を丸ごと削除します。既定ポリシーが drop のチェインが消えると、かえって全面開放の状態になり、逆に他のツールが管理していたルールまで消し飛びます。リモートでは、バックアップと復旧予約なしに絶対に実行しないでください。
恒久設定はファイルで管理し、原子的に適用するのが定石です。
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iif lo accept
ip protocol icmp accept
ip6 nexthdr ipv6-icmp accept
ip saddr 10.0.0.0/8 tcp dport 22 accept
tcp dport { 80, 443 } accept
counter comment "dropped"
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
このファイルを /etc/nftables/main.nft に置き、検査してから適用します。
sudo nft -c -f /etc/nftables/main.nft
sudo nft -f /etc/nftables/main.nft
sudo systemctl enable nftables
nft -f はファイル全体を原子的に適用します。途中で失敗すれば何も適用されないので、ルールが半分だけ入った危険な中間状態は生じません。これが、コマンドを一行ずつ実行するより安全な理由です。
4. firewalld — ゾーンベースの管理
RHEL系の既定ツールです。インターフェースと送信元をゾーン(zone) に割り当て、ゾーンごとに許可ルールを持たせます。
sudo firewall-cmd --state
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all
sudo firewall-cmd --zone=public --list-all
もっとも重要な概念はランタイム設定と恒久設定の分離です。
# ランタイムにのみ適用(再起動時に消える)
sudo firewall-cmd --zone=public --add-service=https
# 恒久設定にのみ反映(いまは適用されない)
sudo firewall-cmd --permanent --zone=public --add-service=https
# 恒久設定をランタイムへ反映
sudo firewall-cmd --reload
# 現在のランタイム状態を恒久設定として保存
sudo firewall-cmd --runtime-to-permanent
--runtime-to-permanent はドキュメントの表現どおり、現在有効なランタイム設定を恒久設定へ上書きします。安全な手順は明確です。まずランタイムにのみ適用して接続を確認し、確認が終わってから恒久保存する、というものです。最初から --permanent を使って --reload する方式は、検証段階がないため危険です。
ポートと送信元の指定です。
sudo firewall-cmd --zone=public --add-port=8080/tcp
sudo firewall-cmd --zone=internal --add-source=10.0.0.0/8
sudo firewall-cmd --zone=public --remove-service=cockpit
sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.3.0/24" port port="5432" protocol="tcp" accept'
恒久設定の文法検査もあります。
sudo firewall-cmd --check-config
--reload と --complete-reload の違いも知っておいてください。ドキュメントによれば --reload は状態情報を維持し、--complete-reload はnetfilterのカーネルモジュールまで再読み込みします。--complete-reload は接続追跡の状態を失い、既存の接続が切れることがあるため、問題解決の目的でのみ使ってください。
5. ufw — 単純さが必要な場所
Ubuntuの既定の管理ツールです。ルール数が少なく、サーバーの役割が単純なときに向いています。
sudo ufw status
sudo ufw status verbose
sudo ufw status numbered
順序が絶対的に重要です。 既定ポリシーを拒否に変える前に、SSHを先に許可しなければなりません。
# 1. まずSSHを許可
sudo ufw allow 22/tcp
# 2. 次に既定ポリシーを設定
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 3. 最後に有効化
sudo ufw enable
破壊的コマンドの警告: この順序を逆にすると、つまりSSHの許可なしに default deny incoming の状態で ufw enable を実行すると、リモート接続が即座に切れます。ufw enable はSSHセッションから実行するときに警告を表示しますが、確認せずに進めればそのまま締め出されます。
ルールの文法です。
sudo ufw allow 80/tcp
sudo ufw allow from 10.0.0.0/8 to any port 22 proto tcp
sudo ufw limit ssh/tcp
sudo ufw deny 3306
sudo ufw delete 3
sudo ufw insert 1 allow from 10.0.3.10
sudo ufw --dry-run allow 8080/tcp
--dry-runは実際には適用せず、どのような変更が起きるかを表示します。適用前に必ず通してください。ufw limitは速度制限です。ドキュメントによれば、一つのIPが30秒以内に6回以上接続を試みると拒否します。SSHの総当たりに対する簡単な緩和策です。sudo ufw delete NUMで削除するときは、先にstatus numberedで番号を確認する必要があります。番号はルールを削除するたびに振り直されるため、複数を削除するときは大きい番号から削除してください。
ロギングと初期化です。
sudo ufw logging on
sudo ufw logging medium
sudo ufw reload
sudo ufw reset
破壊的コマンドの警告: ufw reset はすべてのルールを削除し、インストール時の既定値へ戻します。リモートで実行すると接続が切れることがあります。
6. ルールが適用されないとき — 診断順序
「ルールを入れたのにいまだに遮断される」あるいは「遮断したのにいまだに入ってくる」の診断は、階層ごとに降りていきます。
ステップ1 — 実際のカーネルルールを確認します。 管理ツールの出力ではなく、nftables自体を見る必要があります。
sudo nft list ruleset
sudo iptables -L -n -v --line-numbers
sudo iptables-save | head -40
firewalldやufwを使っていても、最終的なルールは nft list ruleset に現れます。管理ツールが意図どおりに変換したかを、ここで確認します。
ステップ2 — ルールにパケットが当たっているかを数えます。 カウンターを付ければ確実です。
sudo nft add rule inet filter input tcp dport 8080 counter accept
sudo nft list chain inet filter input
カウンターが0なら、そのルールまでパケットが到達していないということです。先行するルールですでに判定されたか、パケットがそもそも到着していないかのどちらかです。
ステップ3 — 順序と重複を確認します。 前方により広い drop ルールがあれば、後ろの accept は評価されません。
ステップ4 — ツールの衝突を確認します。 firewalldとufwを同時に有効にしたり、Dockerが作ったルールと混ざったりすると、予測が難しくなります。
systemctl is-active firewalld ufw nftables iptables
sudo nft list tables
Dockerは独自にルールを挿入します。 そしてそのルールは、ホストファイアウォールの入力チェインではなく別のチェインへ入るため、ホストファイアウォールで遮断したつもりのポートがコンテナ経由で開いている、という状況が生まれます。コンテナのポート公開ポリシーは、ファイアウォールとは別に検討する必要があります。
ステップ5 — 上位の階層を確認します。 クラウドならセキュリティグループやネットワークACLが先に遮断している可能性があります。ホストに到達すらしていないなら、ホストファイアウォールは無実です。
sudo tcpdump -ni eth0 'tcp port 8080' -c 20
パケットがまったく見えなければネットワーク経路の問題であり、見えているのに応答がなければホスト内部の問題です。この一回の確認が調査範囲を半分に減らします。
ステップ6 — ログを見ます。 破棄されるパケットを記録するようにルールを追加できます。
sudo nft add rule inet filter input limit rate 5/minute log prefix '"nft-drop: "' drop
sudo journalctl -k -f -g 'nft-drop'
limit rate を一緒に使わないと、ログが暴走してディスクを埋めます。必ず制限をかけてください。
7. アクセス制御の残りの階層
ファイアウォールだけではアクセス制御は完結しません。階層に分けて整理します。
| 階層 | 手段 | 特徴 |
|---|---|---|
| ネットワーク境界 | クラウドのセキュリティグループ、ACL | ホスト到達前に遮断 |
| ホストファイアウォール | nftables、firewalld、ufw | ポートと送信元の単位 |
| サービス設定 | バインドアドレス、アプリケーションACL | もっとも確実な遮断 |
| 認証 | 鍵、証明書、トークン | 誰であるかの確認 |
| 権限 | ユーザー・グループ、SELinux、sudo | 何ができるか |
もっとも効果的なアクセス制御は、ファイアウォールではなくバインドアドレスです。 サービスがループバックにのみバインドされていれば、ファイアウォールのルールがなくても外部からアクセスできません。
sudo ss -tlnp
0.0.0.0:5432 のようにすべてのインターフェースで開いているサービスを見つけ、本当に外部アクセスが必要かを検討してください。必要ないなら、設定で 127.0.0.1 や内部インターフェースのアドレスに限定するほうが、ファイアウォールのルール一行より確実です。
sudo権限もアクセス制御の一部です。
sudo -l
sudo visudo -c
sudo visudo -f /etc/sudoers.d/deploy
visudo を必ず使ってください。 文法エラーのあるsudoersファイルはsudo自体を使えなくしますし、これも一種の自己締め出し事故です。visudo は保存前に文法を検査して、この事故を防いでくれます。-c は既存ファイルの文法のみを検査します。
SSHのアクセス制限とファイアウォールを合わせて設計する方法は、SSH運用完全ガイドを参照してください。
クイズ: 理解度を確認しましょう
クイズ1: リモートサーバーのファイアウォールルールを大きく変更する必要があります。最初にやることは。
正解: 現在のルールを保存し、一定時間後の自動復旧を予約します
解説: ルールの作成よりも、巻き戻しの準備が先です。
sudo nft list ruleset > /root/nft-backup-2026-08-15.nft
echo "nft -f /root/nft-backup-2026-08-15.nft" | sudo at now + 10 minutes
firewalldなら --timeout オプションが同じ役割を果たします。
sudo firewall-cmd --zone=public --add-port=8080/tcp --timeout=5m
接続が切れても時間が経てば元の状態へ戻るので、最悪の場合でもサーバーを失いません。
クイズ2: ufwで既定の拒否ポリシーを適用しようとしています。正しい順序は。
正解: SSHの許可を先に入れ、既定ポリシーを変更し、最後に有効化します
解説: 順序を逆にすると、有効化された瞬間に接続が切れます。
sudo ufw allow 22/tcp
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw --dry-run enable
sudo ufw enable
--dry-run で適用されるルールを事前に確認する習慣をつけてください。総当たりの緩和が必要なら ufw limit ssh/tcp も検討できます。ドキュメントによれば、30秒以内に6回以上接続を試みるIPを拒否します。
クイズ3: nftablesの入力チェインで必ず前方になければならない二つのルールは何で、なぜですか。
正解: 接続状態の許可と、ループバックの許可です
解説: この二つのルールがないと、正常な通信が広範囲に壊れます。
sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter input iif lo accept
最初のルールがないと、サーバーが外へ送った要求の応答パケットまで遮断され、パッケージのインストールやAPI呼び出しがすべて失敗します。二つ目がないと、ローカルサービス間の通信が切れ、原因を突き止めにくい障害になります。
クイズ4: ファイアウォールで5432ポートを遮断したのに、コンテナのデータベースへ外部から接続できます。なぜでしょうか。
正解: コンテナランタイムが別のチェインへ独自のルールを挿入するからです
解説: Dockerのようなランタイムは、ポートを公開するときに転送関連のルールを独自に入れます。そのルールはホストの入力チェインとは異なる経路で評価されるため、入力チェインだけを遮断しても止まりません。
sudo nft list ruleset | grep -i -A5 'docker'
sudo ss -tlnp | grep 5432
根本的な解決は、コンテナのポートをすべてのインターフェースではなくループバックにのみ公開することです。ポート公開のポリシーは、ファイアウォールとは別に検討する必要があります。
クイズ5: ルールを入れたのに、いまだに接続が遮断されます。原因をどう絞り込みますか。
正解: カウンターでパケットがルールへ到達しているかを確認し、tcpdumpでパケットがホストへ来ているかを確認します
解説: この二つの確認で、調査範囲が大きく減ります。
sudo nft add rule inet filter input tcp dport 8080 counter accept
sudo nft list chain inet filter input
sudo tcpdump -ni eth0 'tcp port 8080' -c 20
tcpdump にパケットがまったく見えなければ、ホストに到達していないということなので、クラウドのセキュリティグループか経路の問題です。パケットは見えるのにカウンターが0なら、先行するルールですでに判定されているので、順序を見る必要があります。
クイズ6: ファイアウォールのルールよりも確実にサービスの露出を防ぐ方法は。
正解: サービスをループバックまたは内部インターフェースにのみバインドします
解説: ファイアウォールは、ルールが誤って削除されたりツールが衝突したりすると突破されます。一方、サービスがそもそも外部インターフェースで待ち受けていなければ、ルールと無関係にアクセスできません。
sudo ss -tlnp
0.0.0.0 や [::] で開いているポートを一覧に出し、一つずつ検討してください。管理ツール、メトリクスのエンドポイント、データベースが全インターフェースで開いている場合はよくあります。ファイアウォールは、その上に載せる二番目の防御線として置くのが妥当です。
おわりに
ファイアウォール作業で覚えておくべきは文法ではなく順序です。巻き戻しを先に予約し、検査し、ランタイムにのみ適用し、新しいセッションで確認し、そのあとで恒久保存します。 この五つの段階を守れば、締め出される事故は起こりません。
そしてツールを選ぶときは規模に合わせてください。単一サーバーにルールが十行ならufwで十分であり、ゾーンとサービスの概念が必要ならfirewalldがよく、ルールをコードとして管理して原子的に配備する必要があるならnftablesのファイルが正解です。 どちらを選んでも、最終結果は nft list ruleset で確認できるという点を覚えておけば、ツール間を行き来するのは難しくありません。
最後にもう一つだけ。ファイアウォールは最後の防御線ではなく、幾重ものうちの一つです。バインドアドレス、認証、権限が一緒に設計されて、はじめて実際に安全になります。
参考資料
- nft(8) — netfilter公式マニュアル (2026-08-15 確認)
- firewall-cmd(1) — firewalld公式ドキュメント (2026-08-15 確認)
- ufw(8) — Ubuntuマニュアル (2026-08-15 確認)
- nftables公式ウィキ (2026-08-15 確認)
関連記事
- 前の記事: ファイルディスクリプタとinode完全ガイド
- 次の記事: DNS 完全ガイド
- シリーズの最初: Linux障害対応コマンド完全ガイド
- SSH運用完全ガイド — アクセス制御の認証階層
- Linuxカーネルパラメータチューニングガイド — ネットワークスタックの調整
- CIDR計算機 — 送信元帯域の計算
- Linuxターミナル — コマンドの練習