2026年9月11日

2026年9月11日

SELinuxの設定と管理方法|WordPressを無効化せずに動かすラベル・ブール値・ログの見方

RHEL系のLinux(AlmaLinux、Rocky Linux、CentOS Stream、Fedoraなど)でWordPressを動かすとき、SELinuxは無効にせず、「ファイルに正しいラベル(タイプ)を付ける」「必要な機能だけブール値で許可する」「拒否ログを読んで原因を特定する」の3つで対処するのが基本です。この記事では、SELinuxの状態の確認から、WordPressのアップロードや更新を通すためのラベル設定、外部APIやリモートDBへの接続許可、拒否ログの読み方、どうしても切り分けが必要なときの安全な一時回避までを順に解説します。

SELinuxの状態を確認する

getenforce
# Enforcing / Permissive / Disabled のいずれかが表示される

sestatus
# 読み込まれているポリシー(通常は targeted)や現在のモードが分かる

3つのモードの意味は次の通りです。

  • Enforcing: ポリシーに反する操作を拒否し、ログに記録する(通常の運用状態)
  • Permissive: 拒否はせず、本来拒否される操作をログに記録するだけ
  • Disabled: SELinuxが動いていない

RHEL系の標準構成では、WebサーバーのApache(httpd)やNginx、PHP-FPMなどのプロセスは httpd_t という種類(ドメイン)として動き、アクセスできるファイルの種類が決められています。プロセスの種類とファイルのラベルは -Z オプションで確認できます。

ps -eZ | grep -E 'httpd|nginx|php-fpm'
ls -Z /var/www/html

後述する semanage コマンドは policycoreutils-python-utils パッケージ、拒否ログを分かりやすく説明する sealert は setroubleshoot-server パッケージに含まれます。入っていなければ dnf install で導入します。

SELinuxが原因かを見分ける

SELinuxによる拒否は、通常のファイル権限(パーミッション)の問題と症状が似ています。次のような状況ではSELinuxを疑います。

  • パーミッションや所有者は正しいのに、403 Forbiddenや「ファイルを開けない」エラーになる
  • メディアのアップロード、プラグインの更新、キャッシュファイルの作成だけが失敗する
  • WordPressから外部APIやリモートのデータベース、SMTPサーバーに接続できない
  • Webサーバーを標準以外のポートで起動しようとすると失敗する

確認の第一歩は、拒否ログ(AVCメッセージ)が記録されているかを見ることです。

# 直近の拒否ログ
sudo ausearch -m AVC,USER_AVC -ts recent

# 拒否された理由の説明を付ける
sudo ausearch -m AVC -ts recent | audit2why

# setroubleshoot-server を入れている場合
sudo sealert -a /var/log/audit/audit.log

ログには denied { write } のような拒否された操作、scontext(操作したプロセスの種類)、tcontext(対象のラベル)、tclass(ファイルかソケットかなど)が記録されます。たとえば scontext=...httpd_t が tcontext=...httpd_sys_content_t のディレクトリへの write を拒否されていれば、「Webサーバーが読み取り専用のラベルが付いた場所に書き込もうとした」と読めます。

ログが何も出ていなければ、原因はSELinux以外(パーミッション、Webサーバーの設定、PHPのエラー)である可能性が高くなります。

WordPressのファイルに正しいラベルを付ける

読み取り用と書き込み用のラベル

Webコンテンツ向けの代表的なラベルは次の2つです。

  • httpd_sys_content_t: Webサーバーが読み取れる(書き込みは不可)
  • httpd_sys_rw_content_t: Webサーバーが読み書きできる

WordPress本体のファイルは読み取りだけで足り、書き込みが必要なのはアップロード先などに限られます。書き込みを許す範囲を狭くするほど、万一PHPの脆弱性を突かれたときの被害を抑えられます。

semanage fcontext でルールを登録する

ラベルは「このパスにはこのラベル」というルールを登録し、restorecon で実際のファイルに反映させる流れで設定します。WordPressを /var/www/wordpress に置いている例です。

# 全体は読み取り用
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/wordpress(/.*)?"

# アップロード先は読み書き用
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/wordpress/wp-content/uploads(/.*)?"

# ルールをファイルに反映(-v で変更内容を表示)
sudo restorecon -Rv /var/www/wordpress

# 登録したルールの確認
sudo semanage fcontext -l | grep wordpress

/var/www/html の配下には最初から読み取り用のラベルが付くルールがあるため、標準の場所に置くなら全体用のルールは不要で、書き込みが必要な場所だけを登録すれば足ります。

chcon コマンドでもラベルは変えられますが、これは一時的な変更で、restorecon やファイルシステム全体のラベル付け直しで元に戻ります。設定として残したいものは semanage fcontext で登録します。

よくあるつまずき: mv で持ち込んだファイル

ホームディレクトリなどで展開したWordPressを mv で /var/www に移動すると、元の場所のラベル(user_home_t など)が残り、Webサーバーから読めずに403になります。cp で複製した場合は移動先のラベルが付くことが多いのですが、どちらの場合も最後に restorecon -Rv を実行しておけば揃います。

更新やキャッシュをどこまで許可するか

管理画面からプラグインやテーマを更新したり、キャッシュ系プラグインを使ったりすると、wp-content 配下の plugins、themes、upgrade、キャッシュ用のディレクトリにも書き込みが必要になります。選択肢は主に2つです。

  • 管理画面からの更新を使うため、必要なディレクトリ(または wp-content 全体)に読み書き用のラベルを付ける
  • Webサーバーには書き込ませず、更新はWP-CLIなど別の手段で行う

前者は手軽ですが、書き込める範囲が広がる分だけ、侵入されたときに不正なPHPファイルを置かれる危険も増えます。運用体制に合わせて選び、どの範囲に書き込みを許したかを記録しておきます。

ブール値で機能を許可する

SELinuxには、よく使われる許可をオン・オフで切り替えられる「ブール値」が用意されています。

# Webサーバー関連のブール値と現在の値
getsebool -a | grep httpd

# 外部へのネットワーク接続を許可(-P で再起動後も保持)
sudo setsebool -P httpd_can_network_connect on

WordPressでよく関係するのは次のものです。

  • httpd_can_network_connect: Webサーバーから外部への接続全般(外部API、別サーバーのRedisなど)
  • httpd_can_network_connect_db: データベースのポートへの接続(DBを別サーバーに置く場合)
  • httpd_can_sendmail: PHPからのメール送信

ブール値は「拒否ログに name_connect が出ていて、宛先が正当なものだと分かった」など、ログで必要性を確かめてから必要なものだけをオンにします。httpd_can_network_connect はWebサーバーからの接続先を広く許すため、DB接続だけが目的なら httpd_can_network_connect_db のように範囲の狭いものを選びます。-P を付けないと再起動で元に戻る点にも注意します。

Webサーバーを標準以外のポートで動かす

リバースプロキシの裏でApacheを別のポートで待ち受けさせる場合などは、そのポートにWebサーバー用の種類(http_port_t)が割り当てられている必要があります。

# http_port_t に割り当てられているポートを確認
sudo semanage port -l | grep -w http_port_t

# 割り当てられていないポートを追加(8082は例)
sudo semanage port -a -t http_port_t -p tcp 8082

そのポートが別の種類ですでに定義されている場合は -a がエラーになるため、-m(変更)を使います。どの種類に割り当てられているかは、上の一覧で確認できます。

切り分けのための一時回避

どうしても原因が分からないときは、システム全体を止めるのではなく、範囲を絞って拒否を止めます。

# システム全体を一時的にPermissiveに(再起動でEnforcingに戻る)
sudo setenforce 0

# Webサーバーの種類だけをPermissiveにする(こちらのほうが範囲が狭い)
sudo semanage permissive -a httpd_t
# 調査が終わったら戻す
sudo semanage permissive -d httpd_t

Permissiveにして症状が消えればSELinuxが原因と分かり、その間に記録された拒否ログが修正の手がかりになります。調査が終わったら、忘れずにEnforcingに戻します。

一部の拒否は、ログを減らすために記録されない設定(dontaudit)になっています。ログに何も出ないのにPermissiveで直る場合は、sudo semodule -DB で一時的にすべて記録させ、調査後に sudo semodule -B で元に戻します。

audit2allow を使うと拒否ログから独自のポリシーモジュールを作れますが、ログに出た操作をそのまま許可するため、本来はラベルの付け間違いが原因だったものまで許してしまうことがあります。まずはラベルとブール値で直せないかを考え、それでも必要な場合だけ、生成された .te ファイルの中身を読んで内容を理解してから読み込みます。

無効化する前に知っておきたいこと

/etc/selinux/config の SELINUX= で起動時のモードを設定できますが、無効化は勧めません。RHEL 9系では設定ファイルでの無効化が推奨されなくなり、カーネルの起動パラメータで無効にする方式が案内されているなど、扱いがバージョンによって変わっています(2026年10月現在)。また、一度Disabledにしてから戻すと、その間に作られたファイルにラベルが付いていないため、ファイルシステム全体のラベル付け直しが必要になり、再起動に時間がかかります。

設定を変える前には、サーバーのスナップショットやバックアップを取り、可能であれば検証用サーバーで同じ手順を試してから本番に反映してください。

まとめ

  • getenforce と sestatus で状態を確認し、拒否ログ(AVC)が出ているかでSELinuxが原因かを見分ける
  • WordPressは全体を読み取り用(httpd_sys_content_t)、アップロード先などだけを読み書き用(httpd_sys_rw_content_t)にする
  • ラベルは semanage fcontext で登録し、restorecon で反映する。chcon は一時的な変更
  • 外部接続やメール送信はブール値で、ログを確認してから必要なものだけ許可する
  • 切り分けは semanage permissive -a httpd_t のように範囲を絞り、終わったら戻す
  • audit2allow や無効化は最後の手段として、内容と影響を理解してから使う

お気軽にご相談ください

お見積りへ お問い合わせへ
▲