SELinux / AppArmor の概要
通常のパーミッションに加えて、より強力にプロセスの行動を縛る仕組みが MAC(強制アクセス制御)です。RHEL/MiracleLinux系では SELinux が、Ubuntu系では AppArmor が採用されています。SELinux はファイルやプロセスに「ラベル」を付け、ポリシーで許可された動きしか認めません。現在の状態は getenforce で確認でき、Enforcing(強制)・Permissive(警告のみ)・Disabled(無効)の3モードがあります。setenforce で一時的にモードを切り替えられます。
これまで見てきたパーミッション(所有者・グループ・その他に対する rwx)は、Linuxの基本的なアクセス制御ですが、これだけでは守りきれない場面があります。たとえば Web サーバのプロセスが乗っ取られた場合、そのプロセスは Web サーバの実行ユーザが持つ権限の範囲で、本来触るべきでないファイルまで読み書きできてしまうかもしれません。パーミッションは「誰が」を見ますが、「そのプロセスが本来やるべき仕事の範囲を超えていないか」までは縛れないのです。この弱点を補うのが MAC(Mandatory Access Control=強制アクセス制御)です。MAC では、管理者が定めたポリシーに反する動作を、たとえファイルの所有者であっても・たとえ root であっても許しません。RHEL/MiracleLinux系ではこの仕組みとして SELinux(selinux)が、Ubuntu系では AppArmor(apparmor)が採用されています。
SELinux と AppArmor のアプローチの違い
SELinux は、ファイル・プロセス・ポートといったあらゆる対象に「ラベル(コンテキスト)」を付け、どのラベルのプロセスがどのラベルの対象にアクセスしてよいかをポリシーで厳密に定義する方式です。きめ細かく強力なぶん、概念はやや難しめです。一方 AppArmor は、プログラムごとに「このアプリはこのパスのファイルだけ触ってよい」というパス基準のプロファイルで縛る方式で、相対的に分かりやすいとされます。どちらも狙いは同じで、「万一あるプロセスが乗っ取られても、そのプロセスがあらかじめ許された範囲しか行動できないようにし、被害の拡大を封じ込める」ことです。これは最小権限の原則を、ユーザ単位ではなくプロセスの振る舞い単位で徹底するもの、と捉えると腑に落ちます。本トラックが前提とする RHEL/MiracleLinux系では SELinux が標準なので、以降は SELinux を中心に説明します。
状態を確認する getenforce と3つのモード
SELinux には3つの動作モードがあります。Enforcing(強制)はポリシー違反を実際にブロックする本番モード、Permissive(警告のみ)は違反をブロックせずログにだけ記録する観察モード、Disabled(無効)は SELinux 自体を止める状態です。現在どのモードかは `getenforce` を実行すると Enforcing のように一語で返ります。より詳しい情報は `sestatus` で、現在のモードと設定ファイル上のモード、ポリシーの種類などをまとめて確認できます。RHEL/MiracleLinux系では既定で Enforcing になっており、これがセキュリティ上望ましい状態です。トラブルが起きると安易に Disabled にしてしまう人がいますが、それは家の鍵を壊して「開かない問題」を解決するようなもので、本来は避けるべき対処です。
モードを切り替える setenforce と恒久設定
モードの切り替えには `setenforce` を使います。`setenforce 0` で Permissive に、`setenforce 1` で Enforcing に、その場で切り替えられます。ただしこの変更は一時的で、再起動すると元に戻ります。これは切り分け作業に便利で、「ある操作が失敗するのは SELinux のせいか?」を確かめたいとき、一時的に Permissive にして同じ操作が通るなら原因は SELinux にある、と判断できます(確認後はすぐ Enforcing に戻します)。恒久的にモードを変えたいときは設定ファイル /etc/selinux/config の SELINUX= 行を書き換えます。注意点として、Disabled と Enforcing/Permissive の間の切り替えは setenforce では行えず、config を編集して再起動する必要があります。なお Disabled から復帰させると、ファイルのラベルが古くなっているため再ラベル付け(autorelabel)が走り、起動に時間がかかることがあります。
ラベルとブール値 — つまずきと正しい直し方
SELinux で初学者が最もつまずくのが、ファイルのラベル(コンテキスト)に起因する「なぜか動かない」現象です。たとえば Web の公開ファイルを既定の /var/www 以外の場所に置くと、SELinux 的にはラベルが合わずアクセスが拒否されます。これを「SELinux を切る」で解決するのは誤りで、正しくはラベルを正す対処をします。一時的には `restorecon -Rv /path` で既定のラベルに戻し、恒久的にそのパスを特定用途として扱わせたいときは `semanage fcontext -a -t httpd_sys_content_t '/srv/web(/.*)?'` のようにルールを追加してから restorecon を当てます。また、特定機能のオン・オフを切り替える「ブール値」という仕組みもあり、`getsebool -a` で一覧、`setsebool -P httpd_can_network_connect on` のように -P 付きで恒久的に有効化できます。違反の記録は /var/log/audit/audit.log に残り、`ausearch -m avc` や sealert で「何が拒否され、どう直せばよいか」のヒントを読み取れます。これらの正攻法を覚えておくと、SELinux を有効に保ったまま問題を解決できます。
実務の使いどころ
実務での勘どころは、「SELinux を切らずに付き合う」ことに尽きます。Enforcing のまま運用し、何か拒否されたら、まずログを見てラベルやブール値で正す——この習慣が、いざ攻撃を受けたときの最後の砦を残します。新しいソフトを既定と違う場所に入れたときや、サービスのポートを変えたときは、SELinux 視点でのラベル設定が要ると意識しておくと、原因究明が速くなります。どうしても切り分けが必要なときだけ一時的に Permissive にして観察し、終わったら Enforcing へ戻す。MAC は通常のパーミッションを置き換えるものではなく、その上に重ねる二段目の防御です。両方を正しく効かせることで、ひとつのプロセスの綻びがシステム全体へ波及するのを防げます。