インフラエンジニアの羅針盤

インフラエンジニア1〜3年目のための技術ガイド

AlmaLinux 9 firewalld 設定リファレンス

公開更新

AlmaLinux 9 のサーバーを運用するうえで、firewalld の設定はネットワーク設定の次に確認すべき項目です。本記事では、firewalld のアーキテクチャからゾーン設計、サービス・ポート許可、リッチルール、ポリシーオブジェクト、ポートフォワーディング、NetworkManager との連携、ログ設定とトラブルシューティングまでを、企業ネットワーク前提で手順化しています。入社1〜3年目のインフラエンジニアが、現場でそのまま使えるリファレンスとして活用できる構成です。

目次
  1. コマンド早見表
  2. 前提条件
  3. 1. firewalld のアーキテクチャ
    1. バージョンとバックエンドの確認
    2. firewalld の構成要素
    3. ランタイム設定と永続設定
  4. 2. ゾーンの設計と管理
    1. 定義済みゾーン一覧
    2. デフォルトゾーンの確認と変更
    3. ゾーン詳細の確認
    4. インターフェースのゾーン割り当て
    5. ソースベースのゾーン割り当て
    6. カスタムゾーンの作成
  5. 3. サービスとポートの許可設定
    1. 定義済みサービスの確認
    2. サービスの追加と削除
    3. ポートの追加と削除
    4. カスタムサービス定義の作成
  6. 4. –permanent / –reload / –runtime-to-permanent の使い分け
    1. パターン A: –permanent → –reload(標準的な方法)
    2. パターン B: ランタイムでテスト → –runtime-to-permanent(推奨)
    3. パターン C: –permanent なしで即時適用(一時テスト用)
  7. 5. リッチルール
    1. 基本構文
    2. 特定 IP からのサービス許可
    3. 特定 IP からの接続拒否
    4. ログ付きリッチルール
    5. レート制限
    6. リッチルールの一覧と削除
  8. 6. ポリシーオブジェクト(ゾーン間通信制御)
    1. ポリシーの作成
    2. ingress / egress ゾーンの設定
    3. ポリシーへのルール追加
  9. 7. IP マスカレードとポートフォワーディング
    1. IP マスカレードの有効化
    2. ポートフォワーディング
    3. 別ホストへのフォワーディング
    4. ip_forward カーネルパラメータ
  10. 8. ダイレクトルールと nftables
    1. ダイレクトルールの確認
    2. nftables ルールの確認
  11. 9. NetworkManager との連携
    1. nmcli でゾーンを設定する
    2. NM 設定と firewall-cmd 設定の優先順位
  12. 10. ログ設定とトラブルシューティング
    1. 拒否パケットのログ有効化
    2. firewalld ログの確認
  13. トラブルシューティング
    1. ランタイムと永続設定の差分を確認する
    2. パケットが拒否されているか確認する
    3. firewalld の問題かアプリの問題か切り分ける
    4. reload と restart の使い分け
    5. パニックモード(全通信遮断)
    6. firewalld が起動しない場合
    7. SELinux との切り分け
    8. クラウドファイアウォール(セキュリティグループ)との二重確認
  14. AlmaLinux 9 総合リファレンスガイド シリーズ一覧

コマンド早見表

やりたいことコマンド
firewalld の状態確認firewall-cmd –state
バージョン確認firewall-cmd –version
デフォルトゾーン確認firewall-cmd –get-default-zone
アクティブゾーン確認firewall-cmd –get-active-zones
現在のルール一覧firewall-cmd –list-all
全ゾーンのルール一覧firewall-cmd –list-all-zones
サービス追加(永続)firewall-cmd –permanent –add-service=http
ポート追加(永続)firewall-cmd –permanent –add-port=8080/tcp
設定の再読み込みfirewall-cmd –reload
ランタイム設定を永続化firewall-cmd –runtime-to-permanent
リッチルール追加firewall-cmd –add-rich-rule=’…’
ゾーン間ポリシー作成firewall-cmd –permanent –new-policy=名前
ポートフォワーディング追加firewall-cmd –add-forward-port=…
拒否パケットのログ有効化firewall-cmd –set-log-denied=all
nftables ルール確認nft list ruleset

前提条件

項目
OSAlmaLinux 9.6
firewalld1.3.4
バックエンドnftables
デフォルトゾーンpublic
実行ユーザーroot 権限(一般ユーザー + sudo)

本記事のコマンド例はすべて root 権限で実行しています。プロンプトが # のコマンドは、一般ユーザーの場合は先頭に sudo を付けて実行してください。

1. firewalld のアーキテクチャ

firewalld は、Linux カーネルのパケットフィルタリング機能をゾーンベースで管理するファイアウォールデーモンです。AlmaLinux 9(RHEL 9)では、バックエンドが iptables から nftables に変更されています。

バージョンとバックエンドの確認

実行コマンド:

# firewall-cmd --version

実行結果:

1.3.4

RHEL 9 / AlmaLinux 9 の firewalld 1.x 系は nftables をバックエンドとして使用します。従来の iptables コマンドは nft 互換ラッパーとして動作するため、iptables -L -n -v でルールを確認することは可能ですが、ルールの追加・変更は firewall-cmd を通じて行います。

firewalld の構成要素

firewalld は以下の要素で構成されています。

  • ゾーン:ネットワークインターフェースや送信元 IP に対して適用する信頼レベルの定義。デフォルトは public
  • サービス:ポート番号とプロトコルの組み合わせに名前を付けたもの(例: ssh = 22/tcp)
  • ポート:サービス定義を使わず、ポート番号を直接指定して許可する
  • リッチルール:送信元 IP やログ出力などの条件を組み合わせた詳細なルール
  • ポリシーオブジェクト:ゾーン間の通信を制御するルール(ダイレクトルールの後継)

ランタイム設定と永続設定

firewalld には「ランタイム設定」と「永続設定」の 2 つの設定領域があります。

  • ランタイム設定:現在動作中の設定。firewalld の再起動や OS 再起動で消える
  • 永続設定/etc/firewalld/ に XML ファイルとして保存される設定。--reload または OS 再起動時に読み込まれる

設定変更を永続化するには、次の 2 つの方法があります。

  1. --permanent オプション付きでコマンドを実行し、その後 --reload でランタイムに反映する(2 ステップ)
  2. ランタイムで設定を変更してテストし、問題がなければ --runtime-to-permanent で一括永続化する

–reload はランタイム設定を上書きする

firewall-cmd --reload は、永続設定でランタイム設定を上書きします。永続化していないランタイム設定は –reload の実行時にすべて消えます。テスト中の設定がある場合は、–reload の前に --runtime-to-permanent で永続化するか、意図的に破棄するかを判断してください。

2. ゾーンの設計と管理

ゾーンは、ネットワークの信頼レベルに応じてトラフィックの許可・拒否ルールをまとめた単位です。インターフェースや送信元 IP をゾーンに割り当てることで、ネットワークセグメントごとに異なるファイアウォールポリシーを適用できます。

定義済みゾーン一覧

実行コマンド:

# firewall-cmd --get-zones

実行結果:

block dmz drop external home internal nm-shared public trusted work

各ゾーンのデフォルトターゲット(マッチしなかったパケットの処理)とユースケースは以下の通りです。

ゾーン名デフォルトターゲットユースケース
dropDROP応答なしで全パケット破棄。外部公開不要なインターフェース
blockREJECTICMP で拒否応答を返す。drop より送信元での障害切り分けが可能
publicdefault(REJECT)デフォルトゾーン。信頼されていないネットワーク向け
externaldefault(REJECT)NAT/マスカレード用。外部ルーター向け
dmzdefault(REJECT)DMZ セグメント。外部公開サーバー向け
workdefault(REJECT)社内ネットワーク。一部サービスを許可
homedefault(REJECT)家庭内ネットワーク向け
internaldefault(REJECT)内部ネットワーク。信頼度が高いセグメント
trustedACCEPT全パケット許可。管理セグメント等、限定的に使用

デフォルトゾーンの確認と変更

デフォルトゾーンは、どのゾーンにも割り当てられていないインターフェースに適用されるゾーンです。

実行コマンド:

# firewall-cmd --get-default-zone

実行結果:

public

デフォルトゾーンを変更する場合は、以下のコマンドを実行します。この変更は即時かつ永続的に反映されます。

実行コマンド:

# firewall-cmd --set-default-zone=internal

切り戻し方法:

# firewall-cmd --set-default-zone=public

ゾーン詳細の確認

特定のゾーンに設定されているルールを確認します。

実行コマンド:

# firewall-cmd --info-zone=public

実行結果:

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0 eth1 eth2 eth3
  sources:
  services: cockpit dhcpv6-client ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

インターフェースのゾーン割り当て

物理サーバーで複数の NIC を持つ場合、各 NIC をそれぞれ異なるゾーンに割り当てて、ネットワークセグメントごとにポリシーを分けることができます。

実行コマンド:

# firewall-cmd --zone=internal --change-interface=eth1

アクティブゾーンを確認して、変更が反映されたことを確認します。

実行コマンド:

# firewall-cmd --get-active-zones

実行結果:

internal
  interfaces: eth1
public
  interfaces: eth3 eth2 eth0

切り戻し方法:

# firewall-cmd --zone=public --change-interface=eth1

ソースベースのゾーン割り当て

仮想サーバーやクラウド環境では NIC が 1 つしかないことが多いため、送信元 IP アドレスでゾーンを割り当てるソースベースの方法が実用的です。

実行コマンド:

# firewall-cmd --zone=trusted --add-source=10.0.1.0/24

10.0.1.0/24 からのパケットは trusted ゾーンのルールが適用されます。管理用ネットワークセグメントからの通信を全許可する場合などに使用します。

切り戻し方法:

# firewall-cmd --zone=trusted --remove-source=10.0.1.0/24

物理サーバーと仮想サーバーでのゾーン設計の違い

物理サーバーは複数の NIC を持つことが多く、NIC ごとにゾーンを割り当てる設計が一般的です。一方、仮想サーバー(特にクラウド環境)は NIC が 1 つであることが多いため、ソースベースのゾーン割り当てが実用的です。クラウド環境ではセキュリティグループ等の外部ファイアウォールと firewalld の二重管理になるため、どちらで何を制御するかをチームで決めておく必要があります。

カスタムゾーンの作成

定義済みゾーンでは要件を満たせない場合、カスタムゾーンを作成できます。カスタムゾーンの作成は永続設定のみで行います。

実行コマンド:

# firewall-cmd --permanent --new-zone=app-segment

作成したゾーンを使用するには、–reload でランタイムに反映します。

実行コマンド:

# firewall-cmd --reload

ホワイトリスト運用(明示的に許可したもの以外をすべて破棄)にする場合は、ゾーンのターゲットを DROP に設定します。

実行コマンド:

# firewall-cmd --permanent --zone=app-segment --set-target=DROP

切り戻し方法(カスタムゾーンの削除):

# firewall-cmd --permanent --delete-zone=app-segment
# firewall-cmd --reload

3. サービスとポートの許可設定

firewalld でのアクセス許可は、サービス名による許可とポート番号による直接指定の 2 つの方法があります。恒久的な設定にはサービス定義を使い、一時的なテストにはポート直指定を使うのが運用上の使い分けの目安です。

定義済みサービスの確認

firewalld にはあらかじめ多数のサービスが定義されています。

実行コマンド:

# firewall-cmd --get-services

特定のサービスの詳細を確認するには、--info-service を使用します。

実行コマンド:

# firewall-cmd --info-service=ssh

実行結果:

ssh
  ports: 22/tcp
  protocols:
  source-ports:
  modules:
  destination:
  includes:
  helpers:

サービスの追加と削除

Web サーバーを公開する場合、http と https サービスを許可します。

実行コマンド:

# firewall-cmd --permanent --add-service={http,https}

実行コマンド:

# firewall-cmd --reload

許可されたサービスの一覧を確認します。

実行コマンド:

# firewall-cmd --list-services

実行結果:

cockpit dhcpv6-client http https ssh

不要なサービスを削除する場合は --remove-service を使用します。AlmaLinux 9 のデフォルトでは cockpit サービスが許可されていますが、使用しない場合は削除します。

実行コマンド:

# firewall-cmd --permanent --remove-service=cockpit

切り戻し方法:

# firewall-cmd --permanent --add-service=cockpit
# firewall-cmd --reload

ポートの追加と削除

サービス定義にないポートを直接指定して許可する場合は --add-port を使用します。

実行コマンド:

# firewall-cmd --permanent --add-port=8080/tcp

ポート範囲を指定する場合は、ハイフンで範囲を記述します。Zabbix Agent のように複数の連続ポートを使用するアプリケーションで使います。

実行コマンド:

# firewall-cmd --permanent --add-port=10050-10051/tcp

実行コマンド:

# firewall-cmd --reload

許可されたポートの一覧を確認します。

実行コマンド:

# firewall-cmd --list-ports

実行結果:

8080/tcp 10050-10051/tcp

切り戻し方法:

# firewall-cmd --permanent --remove-port=8080/tcp
# firewall-cmd --permanent --remove-port=10050-10051/tcp
# firewall-cmd --reload

カスタムサービス定義の作成

自社アプリケーション専用のポートを恒久的に使用する場合は、カスタムサービスを定義します。サービス定義にしておくと、ルール一覧でポート番号ではなくサービス名が表示されるため、運用時の視認性が向上します。

定義済みサービスをテンプレートとしてコピーし、編集する方法が確実です。

実行コマンド:

# cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/myapp.xml

コピーしたファイルを以下のように編集します。

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>MyApp</short>
  <description>Custom service for example.corp application</description>
  <port protocol="tcp" port="8443"/>
  <port protocol="tcp" port="8444"/>
</service>

firewalld を再読み込みしてカスタムサービスを認識させます。

実行コマンド:

# firewall-cmd --reload
# firewall-cmd --info-service=myapp

カスタムサービスをゾーンに追加します。

実行コマンド:

# firewall-cmd --permanent --add-service=myapp
# firewall-cmd --reload

切り戻し方法:

# firewall-cmd --permanent --remove-service=myapp
# firewall-cmd --reload
# rm /etc/firewalld/services/myapp.xml

サービス定義ファイルの配置場所

システム標準のサービス定義は /usr/lib/firewalld/services/ に配置されています。カスタム定義や変更は /etc/firewalld/services/ に配置します。同名のファイルがある場合は /etc/firewalld/services/ が優先されます。SSH のポート番号を変更する場合も、/usr/lib/ 側を直接編集せず、/etc/firewalld/services/ にコピーして編集してください。

4. –permanent / –reload / –runtime-to-permanent の使い分け

firewalld の設定変更には 3 つのパターンがあります。運用シーンに応じて使い分けることで、設定ミスによるサービス断を防止できます。

パターン A: –permanent → –reload(標準的な方法)

設定内容が確定している場合に使用します。手順書に記載する場合はこのパターンが多いです。

実行コマンド:

# firewall-cmd --permanent --add-service=http
# firewall-cmd --reload

–permanent で永続設定に書き込み、–reload でランタイム設定に反映します。–reload を忘れると、永続設定には保存されているがランタイムには反映されていない状態になります。

パターン B: ランタイムでテスト → –runtime-to-permanent(推奨)

本番環境での設定変更に推奨される方法です。まずランタイムに設定を適用して動作を確認し、問題がなければ永続化します。

実行コマンド:

# firewall-cmd --add-service=http

この時点で http が許可されます。Web ブラウザからアクセスして動作を確認します。問題がなければ永続化します。

実行コマンド:

# firewall-cmd --runtime-to-permanent

問題があった場合は、–reload で永続設定に戻すことができます。ランタイムのみの変更なので、永続設定には影響していません。

実行コマンド(問題があった場合の切り戻し):

# firewall-cmd --reload

パターン C: –permanent なしで即時適用(一時テスト用)

–permanent を付けずに実行すると、ランタイム設定のみに反映されます。firewalld の再起動や OS 再起動で設定が消えるため、一時的なテストに使用します。

実行コマンド:

# firewall-cmd --add-port=9090/tcp

OS を再起動するか firewall-cmd --reload を実行すると、この設定は消えます。

運用フローのまとめ

設定確定済み → パターン A(–permanent → –reload)。本番環境での変更 → パターン B(ランタイムテスト → –runtime-to-permanent)。一時テスト → パターン C(–permanent なし、再起動で消える)。パターン B は設定ミス時にも –reload で元に戻せるため、最も安全な手順です。

5. リッチルール

リッチルールは、送信元 IP アドレスの制限、ログ出力、レート制限などの条件を組み合わせた詳細なファイアウォールルールです。サービスやポートの単純な許可・拒否では対応できない要件に使用します。リッチルールはゾーンの通常ルール(–add-service 等)よりも先に評価されます。

基本構文

リッチルールの基本構文は以下の通りです。

rule [family="ipv4|ipv6"] [source address="アドレス"] [service name="サービス名"|port port="ポート" protocol="プロトコル"] [log [prefix="プレフィックス"] [level="レベル"] [limit value="回数/期間"]] [accept|reject|drop]

特定 IP からのサービス許可

管理用ネットワーク(10.0.1.0/24)からの SSH 接続のみを許可するリッチルールです。

実行コマンド:

# firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.0.1.0/24" service name="ssh" accept'

設定されたリッチルールを確認します。

実行コマンド:

# firewall-cmd --list-rich-rules

実行結果:

rule family="ipv4" source address="10.0.1.0/24" service name="ssh" accept

切り戻し方法:

# firewall-cmd --remove-rich-rule='rule family="ipv4" source address="10.0.1.0/24" service name="ssh" accept'

特定 IP からの接続拒否

不正アクセス元として特定された IP アドレスからの全通信を破棄する場合は、drop を指定します。reject ではなく drop を使うことで、攻撃者に対して応答を返さずパケットを破棄します。

実行コマンド:

# firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.0.2.100" drop'

切り戻し方法:

# firewall-cmd --remove-rich-rule='rule family="ipv4" source address="192.0.2.100" drop'

ログ付きリッチルール

SSH アクセスをログに記録する場合は、log オプションを追加します。監査対応やアクセス状況の分析に使用します。

実行コマンド:

# firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.0.1.0/24" service name="ssh" log prefix="SSH_ACCESS" level="info" accept'

ログは journalctl で確認できます。prefix で指定した文字列がログメッセージに含まれるため、フィルタリングに使えます。

レート制限

ログ出力にレート制限を設定することで、大量のログによるディスク圧迫を防止します。

実行コマンド:

# firewall-cmd --add-rich-rule='rule family="ipv4" service name="ssh" log prefix="SSH_ATTEMPT" level="info" limit value="10/m" accept'

limit value="10/m" は 1 分あたり 10 回までログを記録することを意味します。s(秒)、m(分)、h(時間)、d(日)が指定可能です。

リッチルールの一覧と削除

現在のゾーンに設定されているリッチルールを一覧表示します。

実行コマンド:

# firewall-cmd --list-rich-rules

リッチルールを削除する場合は、追加時と同じ構文を --remove-rich-rule に渡します。構文が 1 文字でも異なると削除できないため、--list-rich-rules の出力をコピーして使うのが確実です。

6. ポリシーオブジェクト(ゾーン間通信制御)

ポリシーオブジェクトは、異なるゾーン間のトラフィックを制御する仕組みです。RHEL 9 で非推奨となったダイレクトルールの後継機能として導入されました。物理サーバーで複数のゾーンを運用する場合や、仮想サーバーでソースベースのゾーンを組み合わせる場合に使用します。

ポリシーの作成

internal ゾーンから dmz ゾーンへの HTTP 通信を許可するポリシーを作成します。

実行コマンド:

# firewall-cmd --permanent --new-policy=internal-to-dmz

ingress / egress ゾーンの設定

ポリシーには、トラフィックの入口(ingress-zone)と出口(egress-zone)を設定します。

実行コマンド:

# firewall-cmd --permanent --policy=internal-to-dmz --add-ingress-zone=internal
# firewall-cmd --permanent --policy=internal-to-dmz --add-egress-zone=dmz

ポリシーへのルール追加

ポリシーに対してサービスやポートの許可ルールを追加します。

実行コマンド:

# firewall-cmd --permanent --policy=internal-to-dmz --add-service=http
# firewall-cmd --permanent --policy=internal-to-dmz --add-service=https
# firewall-cmd --reload

ポリシーの設定内容を確認します。

実行コマンド:

# firewall-cmd --info-policy=internal-to-dmz

切り戻し方法(ポリシーの削除):

# firewall-cmd --permanent --delete-policy=internal-to-dmz
# firewall-cmd --reload

ポリシーオブジェクトの使いどころ

物理サーバーで NIC ごとに異なるゾーンを割り当てている場合、ゾーン間の通信制御にポリシーオブジェクトは必須です。仮想サーバーではソースベースのゾーンとポリシーを組み合わせることで、1 つの NIC でもセグメント間の制御が可能です。

7. IP マスカレードとポートフォワーディング

IP マスカレード(SNAT)とポートフォワーディング(DNAT)は、サーバーをルーターや踏み台として動作させる場合に使用します。

IP マスカレードの有効化

サーバーを NAT ゲートウェイとして使用する場合に有効化します。内部ネットワークのホストがこのサーバーを経由して外部にアクセスできるようになります。

実行コマンド:

# firewall-cmd --permanent --add-masquerade
# firewall-cmd --reload

切り戻し方法:

# firewall-cmd --permanent --remove-masquerade
# firewall-cmd --reload

ポートフォワーディング

外部からポート 8080 でアクセスされた通信を、同一サーバーのポート 80 に転送する例です。

実行コマンド:

# firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toport=80

実行コマンド:

# firewall-cmd --reload

設定を確認します。

実行コマンド:

# firewall-cmd --list-forward-ports

実行結果:

port=8080:proto=tcp:toport=80:toaddr=

切り戻し方法:

# firewall-cmd --permanent --remove-forward-port=port=8080:proto=tcp:toport=80
# firewall-cmd --reload

別ホストへのフォワーディング

外部からポート 8080 でアクセスされた通信を、内部ネットワークの別ホスト(10.0.1.50)のポート 80 に転送する場合は、toaddr を追加します。この設定にはマスカレードの有効化と IP フォワーディングが必要です。

実行コマンド:

# firewall-cmd --permanent --add-masquerade
# firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=10.0.1.50
# firewall-cmd --reload

ip_forward カーネルパラメータ

別ホストへのフォワーディングやマスカレードを使用する場合、カーネルの IP フォワーディングが有効になっている必要があります。firewalld の forward: yes 設定が有効であればカーネルパラメータも自動で有効化されますが、念のため確認します。

実行コマンド:

# sysctl net.ipv4.ip_forward

値が 0 の場合は、以下で有効化します。

実行コマンド:

# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.d/99-ip-forward.conf
# sysctl -p /etc/sysctl.d/99-ip-forward.conf

クラウド環境での NAT / ポートフォワーディング

AWS や Azure などのクラウド環境では、NAT Gateway やロードバランサーといったクラウドサービス側の機能を使うのが一般的です。OS 側で IP マスカレードやポートフォワーディングを設定する必要は通常ありません。物理サーバー環境で踏み台サーバーや NAT ゲートウェイを構成する場合に、この章の設定が必要になります。

8. ダイレクトルールと nftables

ダイレクトルールは、firewalld を経由せずに iptables / nftables のルールを直接記述する機能です。RHEL 9 では非推奨(deprecated)となっており、新規の設定ではリッチルールまたはポリシーオブジェクトを使用してください。ただし、既存環境で遭遇する可能性があるため、確認方法を把握しておく必要があります。

ダイレクトルールの確認

実行コマンド:

# firewall-cmd --direct --get-all-rules

出力がなければ、ダイレクトルールは設定されていません。ダイレクトルールが残っている場合は、リッチルールまたはポリシーオブジェクトへの移行を計画してください。

nftables ルールの確認

firewalld が内部的に生成した nftables ルールセットを確認するには、nft コマンドを使用します。トラブルシューティング時に、firewalld の設定が実際にカーネルにどう反映されているかを確認する目的で使います。

実行コマンド:

# nft list ruleset | head -20

実行結果:

table inet firewalld {
	flags owner,persist

	chain mangle_PREROUTING {
		type filter hook prerouting priority mangle + 10; policy accept;
		jump mangle_PREROUTING_ZONES
	}

	chain mangle_PREROUTING_ZONES {
		iifname "eth3" goto mangle_PRE_public
		iifname "eth2" goto mangle_PRE_public
		iifname "eth1" goto mangle_PRE_public
		iifname "eth0" goto mangle_PRE_public
		goto mangle_PRE_public
	}

iptables 互換コマンドでも確認できます。

実行コマンド:

# iptables -L -n -v | head -20

nft コマンドで直接ルールを追加してはいけない

nft add rule ... で直接追加したルールは、firewall-cmd --reload を実行した時点で消えます。firewalld は –reload 時に自身の設定から nftables ルールセットを再生成するためです。ルールの追加・変更は必ず firewall-cmd を通じて行ってください。

9. NetworkManager との連携

NetworkManager(NM)は、ネットワーク接続にゾーンを割り当てる機能を持っています。NM 側でゾーンを設定すると、firewall-cmd で設定したインターフェースのゾーン割り当てよりも NM の設定が優先されます。

nmcli でゾーンを設定する

接続プロファイルにゾーンを割り当てます。

実行コマンド:

# nmcli connection modify eth1 connection.zone internal

設定を反映するには、接続を再アクティブ化します。

実行コマンド:

# nmcli connection up eth1

切り戻し方法:

# nmcli connection modify eth1 connection.zone ""
# nmcli connection up eth1

NM 設定と firewall-cmd 設定の優先順位

NM の接続プロファイルに connection.zone が設定されている場合、firewall-cmd の --change-interface でゾーンを変更しても、NM が接続を再アクティブ化した時点で NM 側の設定に戻ります。インターフェースのゾーン割り当てを恒久的に変更する場合は、nmcli connection modify を使用してください。

NIC 追加時のデフォルトゾーン自動割り当て

新しい NIC を追加した場合、NM は自動的にデフォルトゾーン(通常は public)を割り当てます。意図しないゾーンに割り当てられないよう、NIC 追加後は firewall-cmd --get-active-zones で割り当て状況を確認し、必要に応じて nmcli connection modify でゾーンを変更してください。

NetworkManager の詳細な操作方法は ネットワーク設定編 を参照してください。

10. ログ設定とトラブルシューティング

拒否パケットのログ有効化

firewalld が拒否したパケットをログに記録する設定です。トラブルシューティング時に「パケットが firewalld で落とされているのか、別の原因か」を切り分けるために使用します。

実行コマンド:

# firewall-cmd --set-log-denied=all

現在の設定を確認します。

実行コマンド:

# firewall-cmd --get-log-denied

実行結果:

all

all のほかに unicastbroadcastmulticastoff が指定可能です。通常の調査では all を使用します。

切り戻し方法(ログ出力の無効化):

# firewall-cmd --set-log-denied=off

firewalld ログの確認

firewalld のログは journalctl で確認します。

実行コマンド:

# journalctl -u firewalld

拒否されたパケットをリアルタイムで監視する場合は、-f オプションを付けます。

実行コマンド:

# journalctl -f -k

-k はカーネルメッセージのみを表示するオプションです。firewalld の拒否ログはカーネルの netfilter から出力されるため、このオプションでフィルタリングします。FINAL_REJECTFINAL_DROP というプレフィックスが付いたメッセージが、firewalld によって拒否されたパケットです。

トラブルシューティング

ランタイムと永続設定の差分を確認する

ランタイム設定と永続設定に差分がある場合、意図しない設定漏れが発生している可能性があります。以下のコマンドで比較します。

実行コマンド:

# diff <(firewall-cmd --list-all) <(firewall-cmd --list-all --permanent)

出力がなければ差分はありません。差分がある場合は、ランタイム設定を永続化するか(--runtime-to-permanent)、永続設定をランタイムに反映するか(--reload)を判断してください。

パケットが拒否されているか確認する

通信が通らない原因が firewalld なのかを特定する手順です。

実行コマンド:

# firewall-cmd --set-log-denied=all

別のターミナルでログを監視します。

実行コマンド:

# journalctl -f -k

この状態で対象のクライアントから接続を試行し、ログに拒否メッセージが表示されるかを確認します。表示されれば firewalld が原因です。表示されなければ、アプリケーション側(バインドアドレス、ポートの Listen 状態)を調査してください。

firewalld の問題かアプリの問題か切り分ける

アプリケーションが指定のポートで Listen しているかを確認します。

実行コマンド:

# ss -tlnp

ss -tlnp で対象のポートが表示されない場合、アプリケーションが起動していないか、バインドアドレスが異なっている可能性があります。Local Address:Port 列が 127.0.0.1:ポート になっている場合は、ローカルホストからの接続しか受け付けない設定です。外部からのアクセスを許可するには、アプリケーション側で 0.0.0.0:ポート にバインドする必要があります。

reload と restart の使い分け

firewall-cmd --reloadsystemctl restart firewalld は動作が異なります。

  • reload:永続設定をランタイムに再読み込みする。既存の確立済み接続は維持される。本番環境ではこちらを使用する
  • restart:firewalld デーモンを再起動する。nftables ルールが一度すべて削除され再生成されるため、一時的に全通信が切断される可能性がある

本番環境で restart を使ってはいけない

systemctl restart firewalld は全通信を一時的に切断する可能性があります。本番環境では firewall-cmd --reload を使用してください。restart が必要なケースは、firewalld 自体のアップデート後や、デーモンが応答しなくなった場合に限られます。

パニックモード(全通信遮断)

セキュリティインシデント発生時に、全ネットワーク通信を即座に遮断する最終手段です。

実行コマンド(全通信遮断):

# firewall-cmd --panic-on

解除コマンド:

# firewall-cmd --panic-off

パニックモードは SSH 接続も切断する

--panic-on を実行すると、SSH を含む全通信が遮断されます。リモートから実行した場合、コンソールアクセス(IPMI、iLO、クラウドのシリアルコンソール等)以外の方法でサーバーにアクセスできなくなります。実行前にコンソールアクセスが可能であることを必ず確認してください。

firewalld が起動しない場合

設定ファイルの構文エラー等で firewalld が起動しない場合の対処手順です。

実行コマンド:

# firewall-cmd --check-config

設定ファイルに問題がある場合はエラーメッセージが表示されます。

実行コマンド:

# journalctl -xeu firewalld

このコマンドで firewalld の起動時エラーの詳細を確認できます。カスタムゾーンやカスタムサービスの XML ファイルに構文エラーがある場合は、/etc/firewalld/ 配下の該当ファイルを修正または削除してから再起動してください。

SELinux との切り分け

通信が拒否される原因が firewalld ではなく SELinux である場合があります。特に非標準ポートでアプリケーションを動作させる場合に発生します。

実行コマンド:

# ausearch -m avc -ts recent

SELinux の拒否ログが表示された場合は、semanage port コマンドでポートのラベルを追加する必要があります。詳細は セキュリティ強化編 を参照してください。

クラウドファイアウォール(セキュリティグループ)との二重確認

クラウド環境では、OS 側の firewalld とクラウド側のセキュリティグループの両方でパケットがフィルタリングされます。通信が通らない場合は、両方の設定を確認してください。

  • firewalld で許可しているが、セキュリティグループで許可していない → 通信不可
  • セキュリティグループで許可しているが、firewalld で許可していない → 通信不可
  • 両方で許可している → 通信可能

切り分けの手順として、一時的に firewalld のゾーンを trusted にして通信が通るかを確認する方法があります。通る場合は firewalld の設定が原因、通らない場合はクラウド側の設定が原因です。

SSH ルール変更時の注意

firewalld の設定変更で SSH サービスを削除したり、–reload で永続化していない SSH 許可ルールが消えたりすると、SSH 接続が切断されてリモートからアクセスできなくなります。SSH に関連する設定変更を行う場合は、コンソールアクセスの手段を確保してから作業してください。SSH の詳細な設定は SSH設定編 を参照してください。

AlmaLinux 9 総合リファレンスガイド シリーズ一覧

  1. システム基本情報の確認
  2. 初期設定
  3. ネットワーク設定(nmcli)
  4. パッケージ管理(dnf)
  5. ユーザー・グループ管理
  6. ファイアウォール(firewalld)(この記事)
  7. SSH設定・鍵認証
  8. systemd / サービス管理
  9. ストレージ・LVM
  10. ログ管理(journalctl / rsyslog)
  11. cron / systemd timer
  12. セキュリティ強化
  13. パフォーマンス監視
  14. コンテナ管理(Podman)
  15. バックアップ・リストア
前の記事
次の記事