本記事には広告(アフィリエイトリンク)が含まれます。

SELinux入門 getenforce・restorecon・audit

Linuxエンジニア養成講座 第28回|全36回・フェーズ4「サーバー構築と運用」の第1回目(1/9回目)です。
前回まで: フェーズ3「ネットワークとインフラ基盤」(第16回第27回)で、TCP/IPの基礎からSSH応用までを学びました。
今回学ぶこと: SELinux の設計思想を理解し、コンテキストの確認・修正・監査ログの読み方を実践します。

前回の予告で「SELinux の仕組みと基本操作(getenforce、semanage、restorecon)を学びます。Enforcing のまま運用することの意味と、SELinux が原因でサービスが動かない場合の切り分け方を身につけます」とお伝えしました。今回からフェーズ4「サーバー構築と運用」が始まります。フェーズ4の最初のテーマとして、サーバー構築の土台となる SELinux を取り上げます。

この記事を読み終えると、以下のことができるようになります。

  • SELinux の設計思想(DAC と MAC の違い)を説明できる
  • getenforce / sestatus で SELinux の動作モードとポリシーを確認できる
  • ls -Z / ps -eZ / id -Z でファイル・プロセス・ユーザーのコンテキストを確認できる
  • restorecon でファイルのコンテキストを正しい値に修正できる
  • semanage でポートやブーリアンのルールを確認できる
  • audit.log から SELinux の拒否ログ(AVC deny)を検索できる

なぜ SELinux が必要か

第11回で学んだパーミッション(rwx)を思い出してください。Linux の標準的なパーミッションは DAC(Discretionary Access Control: 任意アクセス制御)と呼ばれます。ファイルの所有者がアクセス権を自由に決められる仕組みです。

DAC には構造的な弱点があります。あるプロセスがセキュリティ上の脆弱性を突かれて侵害された場合、そのプロセスを実行しているユーザーの権限で何でもできてしまいます。たとえば Web サーバー(httpd)が root 権限で動いていれば、侵害された瞬間にサーバー全体が危険にさらされます。

SELinux(Security-Enhanced Linux)は、この問題に対する答えです。SELinux は MAC(Mandatory Access Control: 強制アクセス制御)を実装しています。MAC では、OS が「このプロセスはこのファイルにしかアクセスできない」というルールを強制します。ファイルの所有者やプロセスの実行ユーザーが何であっても、OS が定めたルールを超えることはできません。

具体的な例を挙げます。httpd プロセスは httpd_sys_content_t という type(後述)のファイルしか読めません。仮に httpd が侵害されても、/etc/shadow(パスワードハッシュ)や /var/log/audit/(監査ログ)にはアクセスできません。被害がそのプロセスの許可範囲内に限定されるのです。

これは「最小権限の原則」をOSレベルで実装したものです。第3回で「必要最小限の権限だけを与える」というセキュリティの基本を学びました。SELinux はその考え方をカーネルレベルで強制する仕組みです。

DACとMACの違い。DAC(SELinuxなし)ではhttpdが侵害されると/etc/shadowや/var/log等あらゆるファイルにアクセスできてしまう。MAC(SELinux有効)ではhttpdはhttpd_sys_content_tのファイルにしかアクセスできず、/etc/shadowへのアクセスはブロックされる

だからこそ、SELinux を disable(無効化)にしてはいけません。これはこの講座全体を通じた鉄則です。「SELinux のせいで動かない」と感じたら、disable にするのではなく「なぜ拒否されたのか」を調べて正しく設定することが、インフラエンジニアの仕事です。

SELinux の基本概念

コンテキスト(ラベル)

SELinux では、ファイル・プロセス・ユーザーのすべてに「コンテキスト」と呼ばれるラベルが付きます。コンテキストは次の4つのフィールドで構成されます。

user:role:type:level

たとえば system_u:object_r:httpd_sys_content_t:s0 のような文字列です。4つのフィールドのうち、今の段階で覚えるべきは type(3番目のフィールド)だけです。type が SELinux のアクセス制御の中心です。残りの user、role、level は、まず type を理解してから必要に応じて学べば十分です。

targeted ポリシー

AlmaLinux 9 では targeted ポリシーが使われています。targeted とは「主要なネットワークサービス(httpd、sshd、named など)だけを SELinux で制限し、一般ユーザーのプロセスは制限しない」という方針です。一般ユーザーには unconfined_t(制限なし)という type が付きます。すべてを制限する strict ポリシーもありますが、サーバー用途では targeted が標準です。

3つのモード

SELinux には3つの動作モードがあります。

  • Enforcing — ポリシーに違反するアクセスを拒否し、ログに記録する。本番環境での正しい状態
  • Permissive — ポリシー違反をログに記録するが、アクセスは拒否しない。デバッグ用
  • Disabled — SELinux を完全に無効化する。使わない

この講座では Enforcing を維持します。Permissive は「原因調査のために一時的に切り替える」場面でのみ使い、調査が終わったら必ず Enforcing に戻します。Disabled は選択肢に入れません。

getenforce / sestatus で確認する

現在のモードを確認します。alma-main で実行してください。

実行コマンド:

$ getenforce

実行結果:

Enforcing

getenforce は現在のモードを1行で返します。Enforcing と表示されれば正常です。

より詳細な情報を見るには sestatus を使います。

実行コマンド:

$ sestatus

実行結果:

SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actual (secure)
Max kernel policy version:      33

注目すべきは3つです。Loaded policy name: targeted(targeted ポリシーを使用)、Current mode: enforcing(現在 Enforcing で動作中)、Mode from config file: enforcing(設定ファイルでも Enforcing が指定されている = 再起動しても Enforcing になる)。

ファイルとプロセスのコンテキストを確認する

コンテキストの概念を理解したら、実際に確認してみます。ファイル、プロセス、ユーザーのそれぞれにコンテキストが付いていることを自分の目で確かめてください。

ファイルのコンテキスト(ls -Z)

ls-Z オプションを付けると、ファイルの SELinux コンテキストが表示されます。alma-main で実行してください。

実行コマンド:

$ ls -Z /var/log/ | head -7

実行結果:

          system_u:object_r:var_log_t:s0 README
          system_u:object_r:var_log_t:s0 anaconda
       system_u:object_r:auditd_log_t:s0 audit
          system_u:object_r:faillog_t:s0 btmp
          system_u:object_r:faillog_t:s0 btmp-20260402
  system_u:object_r:chronyd_var_log_t:s0 chrony
         system_u:object_r:cron_log_t:s0 cron

3番目のフィールド(type)に注目してください。var_log_tauditd_log_tchronyd_var_log_tcron_log_t など、ファイルの用途に応じた type が付いています。audit ディレクトリには auditd_log_t が付いているため、auditd 以外のプロセスからはアクセスが制限されます。

SSH 関連のファイルも確認してみます。

実行コマンド:

$ ls -Z /etc/ssh/ | head -5

実行結果:

     system_u:object_r:etc_t:s0 moduli
     system_u:object_r:etc_t:s0 ssh_config
     system_u:object_r:etc_t:s0 ssh_config.d
system_u:object_r:sshd_key_t:s0 ssh_host_ecdsa_key
system_u:object_r:sshd_key_t:s0 ssh_host_ecdsa_key.pub

設定ファイルには etc_t、ホスト鍵には sshd_key_t が付いています。ホスト鍵は sshd が読み取る必要があるため、専用の type で管理されています。

プロセスのコンテキスト(ps -eZ)

ps-eZ オプションを付けると、プロセスの SELinux コンテキストが表示されます。

実行コマンド:

$ ps -eZ | grep sshd

実行結果:

system_u:system_r:sshd_t:s0-s0:c0.c1023 807 ?    00:00:00 sshd

sshd プロセスの type は sshd_t です。SELinux は「sshd_t の type を持つプロセスは sshd_key_t の type を持つファイルを読める」というルールを定義しています。これがコンテキストによるアクセス制御の仕組みです。

ユーザーのコンテキスト(id -Z)

自分自身の SELinux コンテキストも確認できます。

実行コマンド:

$ id -Z

実行結果:

unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

type が unconfined_t です。targeted ポリシーでは、SSH でログインした一般ユーザーは unconfined_t(制限なし)になります。SELinux が制限するのは httpd や sshd などのネットワークサービスであり、ログインユーザーの通常操作は制限されません。

policycoreutils-python-utils を導入する

SELinux のルールを確認・変更するための semanage コマンドは、Minimal Install には含まれていません。policycoreutils-python-utils パッケージを導入します。alma-main で実行してください。

実行コマンド:

$ sudo dnf install -y policycoreutils-python-utils

インストールが完了したら semanage コマンドが使えるようになります。man semanage でマニュアルを確認できるので、どのようなサブコマンドがあるか眺めてみてください。

restorecon でコンテキストを修正する

ここまでで「ファイルやプロセスに type が付いている」ことを確認しました。では、その type が間違っていたらどうなるでしょうか。httpd が読むべきファイルに httpd_sys_content_t ではなく別の type が付いていたら、httpd はそのファイルを読めません。サービスが正常に動かない原因になります。

cp と mv でコンテキストが変わる

ファイルのコンテキストが意図せず変わる、よくある場面を見てみます。

  • cp(コピー) — コピー先の親ディレクトリのデフォルトコンテキストを継承する。元のコンテキストは保持されない
  • mv(移動) — 元のコンテキストをそのまま保持する

この違いが問題を起こします。/tmp でファイルを作成し、/var/www/html/ に cp した場合を実際に見てみます。alma-main で実行してください。

実行コマンド:

$ touch /tmp/selinux-test.txt

作成したファイルのコンテキストを確認します。

実行コマンド:

$ ls -Z /tmp/selinux-test.txt

実行結果:

unconfined_u:object_r:user_tmp_t:s0 /tmp/selinux-test.txt

type は user_tmp_t です。/tmp に作ったファイルなので、一時ファイル用の type が付いています。

このファイルを /var/www/html/ にコピーします。このディレクトリは Apache(httpd)がインストールされると自動的に作成されますが、現時点ではまだ存在しないため、先に作成します。

実行コマンド:

$ sudo mkdir -p /var/www/html

実行コマンド:

$ sudo cp /tmp/selinux-test.txt /var/www/html/

コピー先のコンテキストを確認します。

実行コマンド:

$ ls -Z /var/www/html/selinux-test.txt

実行結果:

unconfined_u:object_r:var_t:s0 /var/www/html/selinux-test.txt

type が var_t になっています。/var/www/html/ のデフォルトコンテキストは httpd_sys_content_t ですが、cp で /var 配下にコピーされたため、途中のディレクトリのコンテキスト(var_t)を継承してしまいました。この状態では httpd はこのファイルを読めません。

restorecon で正しいコンテキストに戻す

コンテキストを修正するコマンドは2つあります。

  • chcon — コンテキストを手動で指定して変更する。一時的な変更であり、restorecon を実行すると元に戻る
  • restorecon — そのパスに対してポリシーで定義された正しいコンテキストに復元する。こちらが正解

chcon は「とりあえず動かしたい」ときに使うことがありますが、再起動やファイルシステムの再ラベリングで消えてしまいます。恒久的な修正には restorecon を使ってください。

先ほどの var_t になってしまったファイルを restorecon で修正します。

実行コマンド:

$ sudo restorecon -v /var/www/html/selinux-test.txt

実行結果:

Relabeled /var/www/html/selinux-test.txt from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

-v オプションを付けると、変更内容が表示されます。var_t から httpd_sys_content_t に修正されたことが分かります。

修正後のコンテキストを確認します。

実行コマンド:

$ ls -Z /var/www/html/selinux-test.txt

実行結果:

unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/selinux-test.txt

type が httpd_sys_content_t に修正されました。これで httpd がこのファイルを読めるようになります。第29回で Apache を構築する際、この知識が必要になります。

ディレクトリ配下を再帰的に修正したい場合は -R オプションを使います。sudo restorecon -Rv /var/www/html/ のように実行すると、ディレクトリ内の全ファイルを一括で修正できます。

semanage でルールを確認する

semanage は SELinux のポリシールールを確認・変更するコマンドです。まずは「確認」の使い方を見ていきます。

ポートのルール確認

SELinux は「どのサービスがどのポートを使えるか」もルールで管理しています。SSH が使えるポートを確認してみます。

実行コマンド:

$ sudo semanage port -l | grep ssh

実行結果:

ssh_port_t                     tcp      22

ssh_port_t に TCP 22 番が割り当てられています。もし SSH を別のポート番号で動かしたい場合は、semanage port -a でそのポートを ssh_port_t に追加する必要があります(firewalld のルール変更に加えて、SELinux のルール変更も必要ということです)。

HTTP 関連のポートも確認します。

実行コマンド:

$ sudo semanage port -l | grep http

実行結果:

http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

http_port_t に TCP 80、443 などが含まれています。httpd がこれら以外のポートで待ち受けようとすると、SELinux に拒否されます。

ブーリアン(ON/OFF スイッチ)

SELinux にはブーリアン(Boolean)という ON/OFF のスイッチがあります。特定の機能を個別に許可・禁止できる仕組みです。getsebool で現在の値を確認できます。

実行コマンド:

$ getsebool -a | grep httpd | head -5

実行結果:

httpd_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_check_spam --> off
httpd_can_connect_ftp --> off
httpd_can_connect_ldap --> off

たとえば httpd_can_connect_ftpoff になっています。httpd から FTP サーバーへの接続は禁止されているということです。必要に応じて setsebool -P httpd_can_connect_ftp on のように変更できます(-P は再起動後も永続化するオプション)。

semanage fcontext -a(ファイルコンテキストのルール追加)や semanage port -a(ポートルールの追加)といった書き込み操作は、第29回で Apache を構築するときに実践します。今回は「確認方法を知っている」ことが目標です。

audit.log の読み方

SELinux がアクセスを拒否すると、/var/log/audit/audit.log に記録されます。このファイルは root のみ読めます。

「SELinux のせいでサービスが動かない」と疑ったとき、最初に確認するのがこのログです。ausearch コマンドで AVC(Access Vector Cache)メッセージを検索します。

実行コマンド:

$ sudo ausearch -m avc --start recent

実行結果:

<no matches>

<no matches> は deny エントリがないことを意味します。SELinux が何も拒否していない = 正常に動作しているということです。

もし deny が記録されていた場合、出力にはどのプロセス(scontext)がどのファイル(tcontext)に対してどの操作(read、write、connectなど)を拒否されたかが記載されます。deny が出ても disable にしないでください。ログの内容を読み、正しいコンテキストを設定するか、ブーリアンを変更するか、ポートを追加するかで対処します。

--start recent は直近10分以内のログを表示するオプションです。時間範囲を指定したい場合は --start 04/04/2026 09:00:00 --end 04/04/2026 10:00:00 のように書くこともできます。詳しくは man ausearch を確認してください。

ヒヤリハット: SELinux を disable にして「解決した」と思った話

ヒヤリハット: 本番環境で SELinux を disable にした

ある現場で、Apache がコンテンツを配信できないトラブルが発生しました。原因は SELinux のコンテキスト不一致だったのですが、担当者は「SELinux のせいで動かない」と判断し、/etc/selinux/configSELINUX=disabled に変更してサーバーを再起動しました。Apache は動くようになり、「解決した」と報告されました。

しかし数か月後のセキュリティ監査で SELinux が無効化されていることが発覚し、重大な指摘事項になりました。本来は restorecon 1発で直る問題でした。「動けば良い」ではなく「なぜ動かないのか」を調べる姿勢が、エンジニアとして問われた事例です。

ヒヤリハット: Permissive のまま本番リリース

開発環境でトラブルシューティングのために Permissive に切り替え、そのまま本番環境にリリースしてしまったケースもあります。Permissive はポリシー違反をログに記録するだけで、アクセスを拒否しません。つまり、SELinux が存在しないのと同じ状態です。

Permissive に切り替えた場合は getenforce で必ずモードを確認し、調査が終わったら sudo setenforce 1 で Enforcing に戻してください。設定ファイル(/etc/selinux/config)側も SELINUX=enforcing のままであることを確認するのが鉄則です。

やってみよう

今回学んだコマンドを使って、以下の課題に取り組んでください。alma-main で実行します。

課題1: ログファイルの type を比較する

ls -Z/var/log/messages/var/log/secure の type を確認してください。2つのファイルの type は同じですか、違いますか。違う場合はなぜ異なる type が付いているか考えてみてください。

ヒント: ls -Z /var/log/messages /var/log/secure で2つ同時に確認できます。

課題2: cp によるコンテキスト変化と restorecon による修正

以下の手順を順番に実行してください。

  1. /tmp に適当な名前のテキストファイルを作成する(touch /tmp/mytest.txt
  2. ls -Z でそのファイルの type を確認する
  3. sudo cp でそのファイルを /var/www/html/ にコピーする
  4. ls -Z でコピー先のファイルの type を確認する(httpd_sys_content_t ではないはず)
  5. sudo restorecon -v でコンテキストを修正する
  6. ls -Z で修正後の type を確認する(httpd_sys_content_t になっているはず)

演習が終わったら、作成したテストファイルを削除しておきます。

実行コマンド:

$ rm /tmp/mytest.txt
$ sudo rm /var/www/html/mytest.txt
$ sudo rm /var/www/html/selinux-test.txt

まとめと次回予告

今回は SELinux の設計思想と基本操作を学びました。ポイントは3つです。

  • 設計思想 — SELinux は最小権限の原則を OS レベルで強制する仕組み(MAC)。プロセスが侵害されても被害を限定できる
  • disable にしない — 動かないときは disable ではなく、audit.log を読んで原因を特定し、コンテキストやポート、ブーリアンを正しく設定する
  • restorecon で修正 — ファイルをコピーしてコンテキストがおかしくなったら restorecon で正しい値に戻す。chcon は一時的な変更なので恒久対応には使わない

次回は第29回「Webサーバー構築(Apache/Nginx)」です。Apache のインストールから設定、自己署名証明書による HTTPS 体験までを行います。今回学んだ SELinux のコンテキスト設定(httpd_sys_content_t)や firewalld のポート許可(80/443)が必要になるので、今回の内容を復習しておいてください。

理解度チェック

今回の内容を振り返り、○×で答えてください。

Q1. SELinux の targeted ポリシーでは、SSH でログインした一般ユーザーのプロセスにも SELinux の制限がかかる。

Q2. SELinux のコンテキストは user:role:type:level の4フィールドで構成され、targeted ポリシーでは type フィールドが最も重要である。

Q3. ファイルを cp でコピーすると、コピー先のファイルは元のファイルの SELinux コンテキストをそのまま引き継ぐ。

Q4. chcon で変更したコンテキストは、restorecon を実行すると元に戻ってしまう。

Q5. SELinux がアクセスを拒否したログは /var/log/audit/audit.log に記録され、ausearch -m avc で検索できる。

Q6. SELinux が原因でサービスが動かない場合、/etc/selinux/config で SELINUX=disabled に変更するのが正しい対処法である。

以下、解答です。

Q1. × — targeted ポリシーでは、一般ユーザーのプロセスは unconfined_t(制限なし)になります。SELinux が制限するのは httpd や sshd などのネットワークサービスです。

Q2. ○ — コンテキストの4フィールドのうち、targeted ポリシーでアクセス制御の中心となるのは type です。「このプロセスの type はこのファイルの type にアクセスできる」というルールで制御されます。

Q3. × — cp はコピー先の親ディレクトリのデフォルトコンテキストを継承します。元のコンテキストを保持するのは mv(移動)です。この違いがコンテキスト不一致の原因になることがあります。

Q4. ○ — chcon による変更は一時的です。restorecon を実行すると、ポリシーで定義された正しいコンテキストに戻されます。恒久的な修正には restorecon を使ってください。

Q5. ○ — SELinux の拒否ログ(AVC deny)は audit.log に記録されます。ausearch -m avc で検索でき、どのプロセスがどのファイルへのどの操作を拒否されたかを確認できます。

Q6. × — disable は絶対に選択肢に入れません。audit.log を読んで原因を特定し、restorecon でコンテキストを修正する、semanage port でポートを追加する、setsebool でブーリアンを変更するなど、正しい方法で対処します。

シリーズ一覧

フェーズ1: エンジニアのいろは(第1回〜第3回)

フェーズ2: Linux基礎(第4回〜第15回)

フェーズ3: ネットワークとインフラ基盤(第16回〜第27回)

フェーズ4: サーバー構築と運用(第28回〜第36回)