2done.org

Linuxメインなメモ書き。二度寝してから書く。(ご意見は Twitter あたりで。そのうちコメント欄つけます。)

Apache の mod_userdir を使う(F14)

2010/12/15

2010/1/2(雑なので書き直すことを決意)

Apache の mod_userdir を使用する場合、SELinux によって目的の操作が拒否されます。(デフォルト)
今回は SELinux が有効な状態で、mod_userdir を動作させる方法を紹介します。
ここでは Apache を RPM からインストールした場合の処理のみ記載します。
ソースからインストールをした場合は頑張ってラベルをつけてください。


1. Apache の設定

/etc/httpd/conf/httpd.conf を編集し UserDir を有効にします。

- UserDir disabled
+ UserDir public_html

 

2. public_html と コンテンツ の作成

ユーザ(2done)のホームディレクトリに ディレクトリ(public_html) と コンテンツ(index.html) を作成します。

# chmod o+x /home/2done
# su - 2done
$ cd /home/2done
$ mkdir public_html
$ echo '<html><body><h1>test</h1></body></html>' > public_html/index.html

$ ls -dZ /home/2done/ && ls -dZ /home/2done/public_html && ls -Z /home/2done/public_html
drwx-----x. 2done 2done unconfined_u:object_r:user_home_dir_t:s0 /home/2done/
drwxrwxr-x. 2done 2done unconfined_u:object_r:user_home_t:s0 /home/2done/public_html
-rw-rw-r--. 2done 2done unconfined_u:object_r:user_home_t:s0 index.html

 

3. 接続テスト(1)

ディレクトリとコンテンツを作成したら接続テストを行います。
恐らく以下のエラーから帰ってくるはずです。404 が帰ってきた場合は色々間違っています。

403(Forbidden)
You don't have permission to access /~2done/ on this server.

 

4. ログの確認

/var/log/audit/audit.log を確認します。以下、抜粋。

# tail /var/log/audit/audit.log
type=AVC msg=audit(1292347281.074:12954): avc:  denied  { search } for  pid=1264 comm="httpd" name="2done" dev=dm-0 ino=530642 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir
type=AVC msg=audit(1292347281.089:12955): avc:  denied  { getattr } for  pid=1264 comm="httpd" path="/home/2done" dev=dm-0 ino=530642 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir

 

Apache のプロセス (scontext=system_u:system_r:httpd_t:s0) がユーザディレクトリ (tcontext=unconfined_u:object_r:user_home_dir_t) に対してディレクトリ内の検索 (search) 及び属性取得 (getattr) を拒否 (denied) しています。

ここでは、inode=530642 のオブジェクトに対して、httpd のアクセスが拒否されています。inode の 530642 が何かは find で確認できます。($ find /home -inum 530642)

 

5. 本当に SELinux が原因か

ログで出ているので確定ですが、設定が間違っていることもあります。
SELinux のモードが Enforcing モードでない状態でも、接続が拒否されるかどうかを確認します。
setenforce コマンドを使用して、SELinux のモードを Permissive モードに切り替えます。

# setenforce 0
# getenforce
Permissive

 

6. 接続テスト(2)

(設定が正しければ)今度は表示されたはずです。SELinux が原因で mod_userdir が使用出来なかった事が確定しました。再度ログを確認します。以下、抜粋。

# tail /var/log/audit/audit.log
type=AVC msg=audit(1292348168.756:12967): avc:  denied  { search } for  pid=1260 comm="httpd" name="2done" dev=dm-0 ino=530642 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir
type=AVC msg=audit(1292348168.756:12967): avc:  denied  { getattr } for  pid=1260 comm="httpd" path="/home/2done/public_html" dev=dm-0 ino=530646 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=dir
type=AVC msg=audit(1292348168.809:12968): avc:  denied  { search } for  pid=1260 comm="httpd" name="public_html" dev=dm-0 ino=530646 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=dir
type=AVC msg=audit(1292348168.832:12969): avc:  denied  { getattr } for  pid=1260 comm="httpd" path="/home/2done" dev=dm-0 ino=530642 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir
type=AVC msg=audit(1292348168.855:12970): avc:  denied  { read } for  pid=1260 comm="httpd" name="index.html" dev=dm-0 ino=530648 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file
type=AVC msg=audit(1292348168.855:12970): avc:  denied  { open } for  pid=1260 comm="httpd" name="index.html" dev=dm-0 ino=530648 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file

 

Permissive モードにしたことで後続の処理まで進み、アクセス拒否のログが増えました。
先ほどまでは、/home/2done へのアクセスが拒否されていたたため、それ以上先には進みませんでした。
Permissive モードでは拒否ログだけ出力し、拒否以降の処理も続行します。

それぞれ、以下のことが拒否されています。

/home/2done(unconfined_u:object_r:user_home_t:s0)                       : search, getattr
/home/2done/public_html(unconfined_u:object_r:user_home_t:s0)           : search, getattr
/home/2done/public_html/index.html(unconfined_u:object_r:user_home_t:s0): read, open

 

7. 許可を与える

やることは2つです。

 

httpd(httpd_t) がユーザホームディレクトリ (user_home_dir_t) に対してアクセスできるようにする

booleanの値を変更します。getsebool コマンドの結果かからそれっぽいものを探し、setsebool コマンドで値を on に変更します。

# getsebool -a | grep httpd | grep home
httpd_enable_homedirs --> off
# setsebool -P httpd_enable_homedirs 1
# getsebool -a | grep httpd | grep home
httpd_enable_homedirs --> on

 

これで、ホームディレクトリ以下の検索・属性の取得が可能になりました。
再度、アクセスをすると、アクセスできるようにな・・・りません。検索・属性の取得はできますが、read が拒否されています。

type=AVC msg=audit(1292350257.832:13010): avc:  denied  { read } for  pid=1260 comm="httpd" name="index.html" dev=dm-0 ino=530648 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file

 

/home/2done/public_html以下のラベルを適切な物に修正する

httpd(httpd_t) は現在のラベル(user_home_t)を読むことが出来ません。
httpd(httpd_t) が読むことを許されたラベルを付与します。事前に定義があるため、restorecon コマンドでラベルは張り直すことで対応が可能です。

# restorecon -RFv /home/2done
restorecon reset /home/2done/public_html context unconfined_u:object_r:user_home_t:s0->unconfined_u:object_r:httpd_user_content_t:s0
restorecon reset /home/2done/public_html/index.html context unconfined_u:object_r:user_home_t:s0->unconfined_u:object_r:httpd_user_content_t:s0
# ls -dZ /home/2done/ && ls -dZ /home/2done/public_html && ls -Z /home/2done/public_html
drwx-----x. 2done 2done unconfined_u:object_r:user_home_dir_t:s0 /home/2done/
drwxrwxr-x. 2done 2done unconfined_u:object_r:httpd_user_content_t:s0 /home/2done/public_html
-rw-rw-r--. 2done 2done unconfined_u:object_r:httpd_user_content_t:s0 index.html

 

これで、httpd(httpd_t) がアクセス可能なラベル (httpd_user_content_t) が張りなおされました。

 

8. 接続確認(3)

SELinux のモードを再度 Enforcing に設定して、アクセスをします。

# setenforce 1
# getenforce
Enforcing

 

今度は無事に表示できたはずでず、これでもまだアクセス拒否をされる場合は、再度 Permissive モードに変更し、直るまで試行錯誤します。
個別に対応が異なるため、ここでは省略をします。頑張ってみてください。

 

9. 最後に

Q. どうやって調べるの?
A. はじめは setroubleshoot を使って調べてみてください。慣れてくればなんとなく法則が見えてきます。
今自分がどうやって調べているのか自分でもわかりません。。ポリシーの中身を見ていたりします。