カタカタブログ

SIerで働くITエンジニアがカタカタした記録を残す技術ブログ。Java, Oracle Database, Linuxが中心です。たまにRuby on Railsなども。

ApacheでSELinuxが原因で403 Forbiddenエラー

Cent OS 7でapacheを使っていて、以下のようなForbiddenエラーが出たときの対処法をメモ。
ちなみに前回のitamaeでのapache起動検証中に発生したエラーで、SELinuxのせいだと気づくのにちょっと時間がかかったので改めて検証した。
Macにitamaeを入れて、Vagrant仮想マシンのプロビジョニングをしてみる - カタカタブログ

Forbidden

You don't have permission to access /index.html on this server.

f:id:osn_th:20150405223457p:plain

結論を言うと、SELinuxが有効な状態で、ファイルが/tmpで作られたhtmlファイルを/var/www/htmlに移動させたため、権限不足でエラーとなってしまっていた。

事象

apacheを起動し、/var/www/html/index.htmlにアクセスすると403 Forbiddenエラーになってしまった。

# ls -l /var/www/html/index.html
-rw-r--r--. 1 root root 15 Apr  5 05:59 /var/www/html/index.html

また、このときapacheのエラーログには以下のように記録されており、権限エラーであることが分かる。

# tail /var/log/httpd/error_log
[Sun Apr 05 09:07:06.075639 2015] [core:error] [pid 1088] (13)Permission denied: [client 192.168.33.1:52446] AH00132: file permissions deny server access: /var/www/html/index.html

一方、このファイルを単純にコピーする。するとコピーしたファイルは正常にapacheで見ることができる。

# cd /var/www/html/
# cp -p index.html index2.html
# ls -l
total 8
-rw-r--r--. 1 root root 15 Apr  5 05:59 index2.html
-rw-r--r--. 1 root root 15 Apr  5 05:59 index.html

f:id:osn_th:20150405223500p:plain

ちなみに、このindex.htmlはitamaeのremote_file機能で配置したもの。このパーミッションの違いは、SELinuxの設定が原因だった。SELinuxのラベルの違いは以下のように確認できる。要するに、httpdはファイルパーミッションやオーナーに関係なく、httpd_sys_content_tラベルがないファイルにはアクセスできないということを意味している。

# ls -Z
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index2.html
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 index.html

index2.htmlは/var/www/htmlで作成されたので、httpd_sys_content_tラベルが付与されている。一方、itamaeで配置したindex.htmlはuser_tmp_tが代わりに付与されている。

これは/tmpで作成されたファイルに対して付与されるラベルになる。

# touch /tmp/index3.html
# ls -Z /tmp/index3.html
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 /tmp/index3.html

そのため、対処法としては以下の2通りがある。

  1. SELinuxを無効化する(ファイルはそのまま)
  2. ラベルを変更する(SELinuxは有効化のまま)

対処法1. SELinuxを無効化する(ファイルはそのまま)

SELinuxを一時的に無効化するには以下のコマンドを実行する。

# setenforce 0

これは即座に反映されるので、index.htmlにアクセスすると以下のように画面が表示される。また、この時点で、403 Forbiddenの原因がSELinuxであったことが分かる。
f:id:osn_th:20150405223503p:plain
先ほどのコマンドは一時的な変更なので、サーバ再起動すると元に戻ってしまう。そこで、恒久的に無効化するためには以下のファイルのSELINUXの値を変更する。値を変更した後、サーバ再起動により反映される。

/etc/sysconfig/selinux

  • SELINUX=enforcing : SELinux有効
  • SELINUX=permissive : SELinuxは無効だが、ポリシー違反があった際に警告が出力される
  • SELINUX=disabled : SELinux無効
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

対処法2: ラベルを変更する(SELinuxは有効化のまま)

SELinuxが無効化できない場合(有効化である設定が正しい場合)、間違っているのはファイルのラベルの方となる。その場合はrestoreconコマンドでラベルのリフレッシュができる。

まず、現在のラベルを再確認しておく。

# ls -Z index.html
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 index.html

restoreconコマンドを実行し、ラベルをリフレッシュする。

# restorecon index.html

現在/var/www/htmlディレクトリにあるindex.htmlは、user_tmp_tラベルが外され、正しくhttpd_sys_content_tラベルが付与されている。

# ls -Z index.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html

この場合は、SELinuxが有効な状態であっても、index.htmlを開くことができるようになっている。

# getenforce
Enforcing

f:id:osn_th:20150405223505p:plain

まとめ

apacheが403 Forbiddenエラーになり、かつファイルパーミッションやファイルオーナーを変更しても解消しない場合、SELinuxの設定を確認してみよう!分かってしまえばなんということはないのだが、Linuxにおいて権限といって、ファイルパーミッションしか意識していないと意外と盲点になりかねないので注意。

関連記事