SELinuxはdisableにするもの、そう考えている人が一般的に多いらしい。
SELinuxについて調べる機会が有り、調べてみたところ、
実は食わず嫌いなだけで、使うだけであればそこまで難しく無いものだと感じた。
せっかくなのでそのまとめ。
SELinuxとは?
DACの仕組みだけに頼らない、セキュリティをより強固にしたもの。
(DACはユーザごとにファイルとかに対してrwxを与える仕組みのこと)
DAC→SELinuxという順番でチェックされるため、DACで弾かれるとSELinuxのチェックは働かない。
動きを簡単にまとめると、プロセスやファイルごとにSELinuxコンテキストという
ラベルみたいなのが設定されていて、そのプロセスに設定されているラベルが
ファイルやディレクトリに設定されているラベルに対して、
読み取りだけとか書き込みもOKとか許可するルールを設定していく感じ。
SElinuxの設定値を見るコマンドとか
- ファイルのSELinuxコンテキストを表示する。
# ls -Z [filename]
-rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
-rw-r--r--. apache apache system_u:object_r:httpd_sys_rw_content_t:s0 avatar.png
(ディレクトリに対しては-dオプションも必要)
- プロセスのSELinuxコンテキストを表示する。
# ps -eZ
system_u:system_r:httpd_t:s0 1223 ? 00:01:34 httpd
- ユーザのSELinuxコンテキストを表示する。
# id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
- コンテキストの見方
SELinuxユーザ:ロール :タイプ :レベル
system_u :object_r:admin_home_t:s0
- コンテキストに設定されているアクセス制御を確認する
sesearch
(setools-consoleパッケージに含まれている)
# sesearch -A -C -s httpd_t -t httpd_sys_content_t
Found 15 semantic av rules:
allow httpd_t file_type : filesystem getattr ;
allow httpd_t file_type : dir { getattr search open } ;
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
allow httpd_t httpd_sys_content_t : dir { ioctl read getattr lock search open } ;
allow httpd_t httpd_sys_content_t : lnk_file { read getattr } ;
allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;
allow httpd_t httpd_content_type : dir { getattr search open } ;
allow daemon httpd_sys_content_t : dir { getattr search open } ;
ET allow httpd_t httpd_sys_content_t : dir { ioctl read write getattr lock add_name remove_name search open } ; [ httpd_enable_cgi httpd_unified && httpd_builtin_scripting && ]
ET allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ; [ httpd_builtin_scripting ]
ET allow httpd_t httpd_content_type : dir { ioctl read getattr lock search open } ; [ httpd_builtin_scripting ]
ET allow httpd_t httpd_content_type : lnk_file { read getattr } ; [ httpd_builtin_scripting ]
ET allow httpd_t httpdcontent : file { ioctl read write create getattr setattr lock append unlink link rename execute open } ; [ httpd_enable_cgi httpd_unified && httpd_builtin_scripting && ]
ET allow httpd_t httpdcontent : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open } ; [ httpd_enable_cgi httpd_unified && httpd_builtin_scripting && ]
ET allow httpd_t httpdcontent : lnk_file { ioctl read write create getattr setattr lock append unlink link rename } ; [ httpd_enable_cgi httpd_unified && httpd_builtin_scripting && ]
httpd_t が httpd_sys_content_tに対しての権限設定を表示。
httpd_tはプロセスのコンテキスト、httpd_sys_content_tはファイルのコンテキスト
-A, --allow :Search for allow rules.
-C :Print the conditional expression and state for all conditional rules found.
This option has no effect on unconditional rules.
(ブール値による設定値の表示を行う。[ ]で囲まれた部分がブール値の設定を表している。)
-s , --source :Find rules with type/attribute NAME as their source.
-t , --target :Find rules with type/attribute NAME as their target.
ブール値
一つ一つ細かくSELinuxの設定を入れなくても、まるごと必要な権限を設定してくれる仕組み
(有名なパッケージだと大体用意されている)
- ブール値一覧表示
# semanage boolean -l
SELinux boolean 状態 初期値 説明
httpd_can_network_connect_db (オン , オン) Allow httpd to can network connect db
ftpd_use_cifs (オフ , オフ) Allow ftpd to use cifs
- ブール値の設定
# setsebool [-P] httpd_can_network_connect_db on
httpdがDBサーバに接続する権限を与える。
-P : 永続設定(これをつけないと再起動時に設定が変更前に戻る)
- ブール値がonかoffか確認する
# getsebool httpd_can_network_connect_db
httpd_can_network_connect_db --> on
一時的な設定変更
- 一時的にコンテキストを変更する
# chcon -t httpd_sys_content_t [filename]
→[filename]にhttpd_sys_content_tを設定する。
-t :ターゲットを指定
-R :ディレクトリを指定する場合
- 元に戻す(永続的に設定されている管理情報を元に、その設定に戻す)
# restorecon -v [filename]
-v : 詳細表示
永続的な設定変更
- 永続的なコンテキスト変更
semanage fcontext
(policycoreutils-pythonパッケージに含まれている)
# semanage fcontext -a -t httpd_sys_content_t [filename]
→[filename]部分は絶対パスじゃないとダメ
-a : コンテキスト追加(add)
-t : ターゲット
実行すると、以下の場所に設定が書き込まれる
/etc/selinux/targeted/contexts/files/
上記ディレクトリにてgrepで何処に設定が書かれたか調べてみる。
# grep test.txt *
file_contexts.local:/home/hoge/test.txt system_u:object_r:httpd_sys_content_t:s0
ディレクトリとその配下のファイルをまるごと変えるには正規表現が必要
# semanage fcontext -a -t httpd_sys_content_t "/home/hoge/testdir(/.*)?"
正規表現で書くと、コンテキスト管理してるファイルも正規表現で記録される
# grep testdir *
file_contexts.local:/home/hoge/testdir(/.*)? system_u:object_r:httpd_sys_content_t:s0
- コンテキストを適用する
# restorecon -v [filename]
-v : 詳細表示
-R : 再帰的に実行(ディレクトリを指定して、その配下まるごと適用する場合等)
実行例
# semanage fcontext -a -t httpd_sys_content_t /home/hoge/test.txt
# ls -Z test.txt
-rw-r--r--. root root unconfined_u:object_r:user_home_t:s0 test.txt
# restorecon -v test.txt
restorecon reset /home/hoge/test.txt context unconfined_u:object_r:user_home_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
# ls -Z test.txt
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 test.txt
# semanage fcontext -a -t httpd_sys_content_t "/home/hoge/testdir(/.*)?"
# restorecon -R -v /home/hoge/testdir
restorecon reset /home/hoge/testdir context unconfined_u:object_r:user_home_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
restorecon reset /home/hoge/testdir/aaa.txt context unconfined_u:object_r:user_home_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
restorecon reset /home/hoge/testdir/bbb.txt context unconfined_u:object_r:user_home_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
- コンテキストを削除する
# semanage fcontext -d "/home/hoge/testdir(/.*)?"
# restorecon -R -v /home/hoge/testdir
restorecon reset /home/hoge/testdir context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:user_home_t:s0
restorecon reset /home/hoge/testdir/aaa.txt context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:user_home_t:s0
restorecon reset /home/hoge/testdir/bbb.txt context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:user_home_t:s0
# ls -lZR
drwxr-xr-x. root root unconfined_u:object_r:user_home_t:s0 testdir
./testdir:
-rw-r--r--. root root unconfined_u:object_r:user_home_t:s0 aaa.txt
-rw-r--r--. root root unconfined_u:object_r:user_home_t:s0 bbb.txt
ポートの変更
SELinuxではネットワークの使用するポートも管理されている。
ポートを独自のものに変えた場合、設定変更が必要。
- 設定一覧表示
# semanage port -l
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
→設定されてるポート表示
- ポート設定追加
# semanage port -a -t http_port_t -p tcp 12345
- ポート設定削除
# semanage port -d -t http_port_t -p tcp 12345
ファイルシステムについて
ファイルシステムをマウントするときもSELinuxのコンテキストを指定することができる。
SambaとかでNFS使う場合に便利?
- mountコマンド実行時に指定
# mount sever:/export /local/mountpoint -o context="system_u:object_r:httpd_sys_content_t:s0"
-o : mountコマンドのオプション指定
- mountの永続化
/etc/fstab に記述することで永続化される。
sever:/export /local/mountpoint nfs context="system_u:object_r:httpd_sys_content_t:s0" 0 0
httpdについて
よく使われるhttpdについて(apacheもnginxもプロセスはともにhttpd_t)
- タイプについて
httpd_sys_content_t : httpdプロセスが"読み取り"のみ可。書き込みは不可。
httpd_sys_rw_content_t : 読み書き可
httpd_sys_script_exec_t : スクリプト実行可
auditログを用いた設定
SELinuxは/var/log/audit/audit.log に色々とログが残る。
audit.logを元に許可ルールを作成することができる。
- audit.logについて、人が読みやすいようにログを変換する。
# audit2allow -a
#============= httpd_t ==============
#!!!! This avc can be allowed using one of the these booleans:
# nis_enabled, httpd_can_network_relay, httpd_can_connect_ftp, httpd_can_network_connect
allow httpd_t ftp_port_t:tcp_socket name_connect;
#!!!! This avc can be allowed using one of the these booleans:
# httpd_can_network_relay, httpd_can_network_connect
allow httpd_t http_cache_port_t:tcp_socket name_connect;
#!!!! This avc can be allowed using the boolean 'httpd_unified'
allow httpd_t httpd_sys_content_t:dir { write remove_name create add_name setattr };
#!!!! This avc can be allowed using the boolean 'httpd_unified'
allow httpd_t httpd_sys_content_t:file { write create unlink setattr };
allow httpd_t postfix_etc_t:file read;
- 拒否されたものに対して、許可ルールを作成する
# audit2allow -a -M test
******************** IMPORTANT ***********************
To make this policy package active, execute:
semodule -i test.pp
test.ppと test.teが作成される
.pp: ポリシーパッケージ
.te: タイプエンフォースメントファイル
→タイプエンフォースメントファイルのルールをコンパイルしてポリシーパッケージを作成する。
.teの中身
# cat test.te
module test 1.0;
require {
type postfix_etc_t;
type httpd_t;
type ftp_port_t;
type httpd_sys_content_t;
type http_cache_port_t;
class tcp_socket name_connect;
class dir { write remove_name create add_name setattr };
class file { read write create unlink setattr };
}
#============= httpd_t ==============
#!!!! This avc can be allowed using one of the these booleans:
# nis_enabled, httpd_can_network_relay, httpd_can_connect_ftp, httpd_can_network_connect
allow httpd_t ftp_port_t:tcp_socket name_connect;
#!!!! This avc can be allowed using one of the these booleans:
# httpd_can_network_relay, httpd_can_network_connect
allow httpd_t http_cache_port_t:tcp_socket name_connect;
#!!!! This avc can be allowed using the boolean 'httpd_unified'
allow httpd_t httpd_sys_content_t:dir { write remove_name create add_name setattr };
#!!!! This avc can be allowed using the boolean 'httpd_unified'
allow httpd_t httpd_sys_content_t:file { write create unlink setattr };
allow httpd_t postfix_etc_t:file read;
- ポリシーパッケージを適用する
# semodule -i [filename].pp
(teじゃなくてppを指定すること)
- 複数あるログから、特定のルールのみを作りたい場合はgrepを使う
# grep httpd /var/log/audit/audit.log | audit2allow -a
# grep httpd /var/log/audit/audit.log | audit2allow -a -M httpd_pol
# cat httpd_pol.te
module httpd_pol 1.0;
require {
type httpd_t;
type httpd_sys_content_t;
class dir { write remove_name add_name };
class file { write create unlink setattr };
}
#============= httpd_t ==============
#!!!! This avc can be allowed using the boolean 'httpd_unified'
allow httpd_t httpd_sys_content_t:dir { write remove_name add_name };
#!!!! This avc can be allowed using the boolean 'httpd_unified'
allow httpd_t httpd_sys_content_t:file { write create unlink setattr };