Permission Deniedエラーに騙されないで
Fedoraをメインの開発マシンとして2年ほど使っていますが、その安定性には非常に満足しています。しかし、Ubuntuから移行したばかりの人が必ずと言っていいほど直面する「罠」があります。特にFedora Serverをインストールした直後などは、Nginxをインストールし、chmod 755で権限を設定し、設定ファイルも完璧なのに、アクセスすると 403 Forbidden が発生するケースです。ログを確認すると、そこには挑戦状のように AVC denied の文字が並んでいます。
ネット上の記事の9割は「手っ取り早く setenforce 0 しよう」と教えてくれるでしょう。でも、その言葉を鵜呑みにしてはいけません。それは、鍵の回りが少し悪いからといって、ドアの鍵をすべて取り外してしまうような, 非常に非プロフェッショナルな対応です。セキュリティを無効化するのではなく、SELinuxに自分の意図を理解してもらうための「交渉術」を学びましょう。
「AVC denied」という悪夢を解読する
SELinuxを、Mandatory Access Control (MAC) に基づいて動作する厳格なガードマンだと考えてください。SELinuxは、あなたが root 権限を持っているかどうかは気にしません。プロセスとファイルのラベル(label)が一致しない限り、リスクを未然に防ぐためにその動作を即座にブロックします。このイベントが AVC denied としてログに記録されます。
始める前に、システムで保護モードが有効になっていることを確認しましょう。
sestatus
もし Current mode: enforcing と表示されていれば、準備は万端です。
setroubleshootを使ってログを「人間が読める言葉」に翻訳する
/var/log/audit/audit.log にある生のログファイルは、正直に言って解読が困難な情報の塊です。幸いなことに、Fedoraには setroubleshoot が用意されています。これは、難解なコードの羅列を分かりやすいヒントに変換してくれるツールです。また、システムエラーの全体像を把握するには、ABRTによるデバッグとエラー報告の自動化についても知っておくと、トラブル解決の幅が広がります。
ツールのインストール
Server版やMinimal版を使用している場合は、以下のコマンドで追加してください。
sudo dnf install setroubleshoot-server -y
sealert de原因を突き止める
例えば、Nginxが起動しないとしましょう。当てずっぽうで探るのではなく、過去1時間に発生したエラーについてシステムに説明を求めます。
sudo journalctl -t setroubleshoot --since "1 hour ago"
さらに詳細を知りたい場合は、ログからエラーIDをコピーして実行します。
sudo sealert -l [エラーID]
すると、sealert は 「何がブロックされたのか?」「なぜか?」 を明確に示してくれます。さらに、コピー&ペーストするだけで30秒以内にエラーを修正できる解決コマンドまで提示してくれます。
ラベルの再割り当て(Labeling)による修正
最も一般的なSELinuxエラーは、ファイルの移動によるものです。例えば、/home/user/project から /var/www/html へコードを移動した場合、ファイルにはHomeディレクトリのラベルが付いたままになり、Nginxがアクセスできなくなります。
SELinuxを無効化する代わりに、これが正当なWebデータであることを教えてあげましょう。
# 新しいパスにラベルを登録する
sudo semanage fcontext -a -t httpd_sys_content_t "/my/custom/path(/.*)?"
# 実際にファイルに変更を適用する
sudo restorecon -Rv /my/custom/path
このコマンドにより、そのディレクトリ内のすべてのファイルがWebサーバーに属していることをシステムが理解します。安全で、かつ非常にスマートな解決策です。このラベル管理の概念は、Redisのインストールと設定など、他のミドルウェアを導入する際にも必ず役立ちます。
万策尽きた時のカスタムポリシー作成
アプリケーションが特殊なポートを使用していたり、MariaDBをProduction環境で構築する際のように標準のラベルではサポートされていない特定の動作を必要としたりすることがあります。そんな時に役立つのが audit2allow です。
例えば、システムディレクトリにログを書き込む必要があるPythonスクリプトがブロックされ続けているとします。以下の3つの手順に従ってください。
1. ログからエラーを抽出する
Pythonに関連するブロックイベントをフィルタリングし、ポリシー定義ファイル(.te)に変換します。
sudo ausearch -c "python3" --raw | audit2allow -m my_python_script > my_python_script.te
2. ポリシー内容を確認する
作成された .te ファイルを開きます。特定のアクセス権限を許可する構造が表示されます。例:
allow httpd_t user_home_t:file { write create };
アプリケーションに過剰な権限を与えていないか、内容をよく確認してください。
3. 新しいポリシーを有効化する
問題がなければ、コンパイルしてLinuxカーネルにロードします。
checkmodule -M -m -o my_python_script.mod my_python_script.te
semodule_package -o my_python_script.pp -m my_python_script.mod
sudo semodule -i my_python_script.pp
完了です!これで、システムのセキュリティレベルを下げることなく、アプリケーションをスムーズに動作させることができます。
クイックデバッグのコツ
エラーの原因がコードにあるのかSELinuxにあるのか迷ったときは、一時的に Permissive モードに切り替えてみましょう。
sudo setenforce 0
このモードでは、SELinuxは監視とログ記録のみを行い、ブロックはしません。もしこの状態でアプリケーションが動作するなら、原因は間違いなくラベルのエラーです。テストが終わったら、安全のために必ず sudo setenforce 1 で設定を戻すのを忘れないでください。
最後に
SELinuxを使いこなすことは、単にツールをインストールできる人から、真のシステムエンジニアへとステップアップすることを意味します。audit2allow を使うわずか5分の手間で、WireGuard VPNの導入などを含め、サーバーを数多くの潜在的なセキュリティリスクから守ることができます。安易な道ではなく、プロフェッショナルな道を選びましょう!

