SELinuxをEnforcingモードで運用するサーバーでは、こうした拒否エラーは日常的に発生します。真っ先に思いつく対処は「setenforce 0 でSELinuxを無効化する」ですが、それではせっかくの強制アクセス制御が無駄になります。パッケージアップデートのタイミングで再度 Enforcing に戻った瞬間、また同じ問題が繰り返されます。
この記事では、audit2allowコマンドを使ってSELinuxのAVC拒否エラーを正しく解消する方法を、実機の出力例を交えて解説します。auditログからカスタムポリシーモジュールを生成してsemoduleで適用するまでの一連の手順を体系的にまとめます。
実行環境:Rocky Linux 9.4 / RHEL 9.4 で動作確認済み
この記事のポイント
・audit2allow -M でAVCログからポリシーモジュールを生成する
・semodule -i mymod.pp の1コマンドでポリシーを即座に反映できる
・適用前に .te ファイルを確認して最小権限を守ること
・全ログを無差別に渡すと別プロセスの権限が混入するリスクがある
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜSELinuxが「Permission denied」を起こすのか
SELinux(Security-Enhanced Linux)はLinuxカーネルに組み込まれた強制アクセス制御(MAC)機能です。通常のUNIXパーミッション(chmodで設定するDAC)とは独立して動作し、「どのプロセスが、どのファイルやポートに、どの操作をできるか」を細かく制限します。この制限を実現するのがSELinuxポリシーです。ポリシーに書かれていないアクセスはすべて拒否され、その記録が
/var/log/audit/audit.log にAVC(Access Vector Cache)拒否ログとして書き込まれます。つまり、audit.log の AVC denied メッセージは「不正アクセスの証拠」ではなく、「ポリシーで想定されていない正当なアクセスが拒否されている」という意味であるケースがほとんどです。audit2allowはこのAVCログを解析し、必要最小限の許可ルールを自動生成してくれるツールです。
セキュリティの観点から見ると、audit2allowで作成したカスタムポリシーは「SELinuxを壊さずに特定の操作だけ追加で許可する」アプローチです。setenforce 0(無効化)や permissive モードへの変更とは根本的に異なります。
audit2allowを使う前の準備
1. SELinuxの状態と必要ツールを確認する
まず現在のSELinuxの動作モードを確認します。# SELinuxの動作モードを確認 getenforce sestatus
[root@web01 ~]# getenforce Enforcing [root@web01 ~]# sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux mode from config file: enforcing Policy MLS status: enabled Policy deny_unknown status: allowed Max kernel policy version: 33
policycoreutils-python-utils パッケージに含まれています。# audit2allowが使えるか確認 which audit2allow # 入っていない場合はインストール(Rocky Linux 9 / RHEL 9) dnf install -y policycoreutils-python-utils
2. AVCログを絞り込む(ausearch・grep)
audit2allowを使う前に、対象のAVCログを正確に絞り込むことが重要です。全ログを無差別に渡すと、関係ないプロセスの操作まで許可してしまうリスクがあります。ausearchコマンドを使うと、プロセス名・時間帯・メッセージタイプを指定して絞り込めます。
# 最近のAVC拒否ログを抽出(-ts recent = 直近10分) ausearch -m AVC -ts recent # 特定プロセス(nginx)のAVC拒否ログを本日分だけ抽出 ausearch -m AVC -c nginx -ts today # 日時を指定して絞り込む(例:今日の10:00以降) ausearch -m AVC -ts 10:00 # grepで絞り込む場合(ausearchが使えない環境向け) grep "AVC" /var/log/audit/audit.log | grep 'comm="nginx"'
systemctl status auditd)。audit2allowでポリシーモジュールを作成する
1. ausearch | audit2allow -M でモジュールを生成する
ausearchで絞り込んだAVCログをパイプでaudit2allowに渡し、ポリシーモジュールを生成します。# Nginx用のカスタムポリシーモジュールを生成 ausearch -m AVC -c nginx -ts today | audit2allow -M mynginx
・
mynginx.te:人間が読めるポリシーソース(Type Enforcement)・
mynginx.pp:コンパイル済みポリシーパッケージ(semoduleで適用するファイル)2. .te ファイルで何を許可するか確認する
semodule -i を実行する前に、必ず .te ファイルの内容を確認してください。意図しないプロセスへの許可が含まれていないかチェックします。# 生成されたポリシーの内容を確認 cat mynginx.te
module mynginx 1.0; require { type httpd_t; type var_t; class file { open read getattr }; } #============= httpd_t ============== allow httpd_t var_t:file { open read getattr };
httpd_t(NginxやApacheが動くSELinuxドメイン)が var_t(/var 配下のデフォルトコンテキスト)のファイルに対して read・open・getattr の操作を許可する」というルールだとわかります。確認のポイントは次の2点です。
・想定外のドメイン(
unconfined_t など)が含まれていないか・許可している操作クラスが過剰でないか(
execute や write が意図せず含まれていないか)3. semodule -i でポリシーを適用する
内容を確認したら .pp ファイルをシステムに適用します。# ポリシーモジュールを適用 semodule -i mynginx.pp # 適用されたことを確認 semodule -l | grep mynginx
[root@web01 ~]# semodule -i mynginx.pp [root@web01 ~]# semodule -l | grep mynginx mynginx 1.0
# サービス再起動 systemctl restart nginx # AVC拒否が解消されたか確認 ausearch -m AVC -c nginx -ts recent # 何も出力されなければ成功
よくあるパターン別の実践例
1. httpd(Apache・Nginx)がカスタムディレクトリを読めない場合
/var/www/html 以外のディレクトリ(例:/data/web)にドキュメントルートを設定したとき、httpdはそのディレクトリのSELinuxコンテキストが httpd_sys_content_t でないと読めません。このケースでは、audit2allowよりも semanage fcontext + restorecon を使う方法が推奨です。コンテキストを正しく設定することで、拒否の根本原因を解消できます。
# 方法A:/data/web のSELinuxコンテキストを httpd_sys_content_t に変更(推奨) semanage fcontext -a -t httpd_sys_content_t "/data/web(/.*)?" restorecon -Rv /data/web # 方法B:audit2allowでカスタムポリシーを作る(複雑なケース向け) ausearch -m AVC -c httpd -ts today | audit2allow -M myhttpd cat myhttpd.te semodule -i myhttpd.pp
2. カスタムサービスがネットワーク接続できない場合
SELinuxには「どのドメインがどのポートに接続できるか」のポリシーもあります。例えば、Nginxをリバースプロキシとして動かし、上流サービスの8080番ポートに接続しようとして拒否されるケースがよくあります。このケースでは semanage port でポートのSELinuxタイプを設定する方法が優先です。
# 方法A:8080番ポートに http_port_t タイプを追加(推奨) semanage port -a -t http_port_t -p tcp 8080 # 現在定義されているポートのSELinuxタイプを確認 semanage port -l | grep http_port_t # 方法B:audit2allowでポリシーを作る場合 ausearch -m AVC -c nginx -ts today | audit2allow -M nginx_port cat nginx_port.te semodule -i nginx_port.pp
3. cronジョブがスクリプトを実行できない場合
/etc/cron.d/ 経由で実行するスクリプトが、SELinuxによって拒否されることがあります。特にスクリプトが /tmp や /home 配下のファイルを操作したり、別のコマンドを呼び出したりするときに crond_t ドメインの制約に引っかかります。# cron関連のAVC拒否ログを抽出 ausearch -m AVC -c crond -ts today ausearch -m AVC -c run-parts -ts today # ポリシーモジュールを生成・内容確認・適用 ausearch -m AVC -c crond -ts today | audit2allow -M mycron cat mycron.te semodule -i mycron.pp
audit2allowを使う際の3つの注意点
注意1:audit2allow -a(全ログ対象)は使わないaudit2allow -a は audit.log 全体を対象とするため、直近の全AVC拒否が混在します。関係ないプロセスへの許可も含まれてしまうため、必ず ausearch で絞り込んでからパイプで渡してください。注意2:.te ファイルを必ず目視確認する
生成された .te ファイルには「allow ドメイン タイプ:クラス { 操作一覧 }」という形式でルールが記述されています。想定外のドメインや、過剰な操作クラス(
execute や write など)が含まれていないか確認してから semodule -i を実行します。注意3:カスタムモジュールの管理を記録しておく
適用したモジュール名は
semodule -l で確認でき、不要になれば semodule -r モジュール名 で削除できます。誰が・いつ・何の目的でポリシーを追加したかを運用記録として残すことを習慣にしてください。サーバーを長期運用すると、誰が作ったかわからないカスタムポリシーが蓄積してしまいます。# 適用済みカスタムモジュールの一覧確認 semodule -l # 不要なモジュールを削除 semodule -r mynginx
トラブルシュート(よくあるエラー)
1. ausearch で何も出力されない
auditdサービスが停止しているか、ログローテーションで古いログが削除されている可能性があります。# auditdの状態確認 systemctl status auditd # auditdが停止していたら起動する systemctl start auditd systemctl enable auditd # ローテーション後のログも含めて検索する ausearch -m AVC -ts 2026-08-01 --input-logs
2. semodule -i が「Failed」で終わる
ディスクの空き容量不足か、SELinuxポリシーデータベースの不整合が原因のことが多いです。# ディスク容量確認(/usr/share/selinux への書き込みが必要) df -h /usr # policycoreutils のバージョン確認 rpm -q policycoreutils policycoreutils-python-utils # SELinuxストアを再構築する(最終手段) semodule -B
3. ポリシー適用後もまだ Permission denied が出る
・適用したモジュールが正しくロードされているかsemodule -l | grep モジュール名 で確認する・サービスを再起動せずにファイルにアクセスしている場合はプロセスを再起動する
・auditログに別の avc: denied がないか再確認する(1つ解消すると次の拒否が出ることがある)
・SELinuxのコンテキストが変わっていないか
ls -Z 対象ファイル で確認する本記事のまとめ
audit2allowを使ってSELinuxの拒否エラーを解消する手順をまとめます。| やりたいこと | コマンド |
|---|---|
| SELinuxの動作モードを確認 | getenforce |
| AVC拒否ログを抽出(プロセス絞り込み) | ausearch -m AVC -c nginx -ts today |
| ポリシーモジュールを生成 | ausearch -m AVC -c nginx | audit2allow -M mynginx |
| 生成内容の確認 | cat mynginx.te |
| ポリシーを適用 | semodule -i mynginx.pp |
| 適用済みモジュールを確認 | semodule -l |
| カスタムモジュールを削除 | semodule -r mynginx |
SELinuxのポリシー管理をマスターしたら、次はLinuxサーバー全体のセキュリティ設計を体系的に固めませんか?
SELinuxをEnforcingモードで正しく運用できるエンジニアは、現場で確実に信頼されます。ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Linuxサーバーのメモリ不足を早期発見する監視設計|free・vmstat・/proc/meminfoを組み合わせた実践手順
- この記事の属するカテゴリ:Linuxtips・セキュリティへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます