CentOS 6.5で動作するApache 2.2を介して複数のバージョンのphpを実行するために、php-fpmの複数のインスタンスを設定しようとしています。
将来のある時点で、これは共有ホスティング環境になってしまうので、できる限り厳しいセキュリティが必要です。
したがって、selinuxを完全に無効化しないようにし、ポリシーをできるだけ狭く設定するようにしています。
私は比較的selinuxを使い始めたばかりです(既存のサーバーでは単に無効になっています)。私はトピックについて多くの読書をしましたが、ロジックはまだ私から逃れています(この質問が示すと確信しているので)。
Php-scriptを呼び出すと、Apacheは次のエラーを生成します。
[Sun May 18 10:46:17 2014] [error] [client 192.168.163.1] (13)Permission denied: FastCGI: failed to connect to server "/fcgi-bin-php5-fpm-i10000_test-1.testtest.org": connect() failed
[Sun May 18 10:46:17 2014] [error] [client 192.168.163.1] FastCGI: incomplete headers (0 bytes) received from server "/fcgi-bin-php5-fpm-i10000_test-1.testtest.org"
Php-fpmソケットを含むディレクトリは次のようになります。
drwxr-xr-x. root root system_u:object_r:var_run_t:s0 .
drwxr-xr-x. root root system_u:object_r:var_run_t:s0 ..
srw-------. Apache apache unconfined_u:object_r:var_run_t:s0 Apache_default.sock
srw-------. Apache apache unconfined_u:object_r:var_run_t:s0 i10000_test-1.testtest.org.sock
srw-------. Apache apache unconfined_u:object_r:var_run_t:s0 i10000_test-2.testtest.org.sock
srw-------. Apache apache unconfined_u:object_r:var_run_t:s0 i10000_test-3.testtest.org.sock
-rw-r--r--. root root unconfined_u:object_r:var_run_t:s0 php-fpm-5.3.pid
-rw-r--r--. root root unconfined_u:object_r:initrc_var_run_t:s0 php-fpm.pid
それに基づいて、ソケットのタイプはvar_run_t
...であると想定します。
だから私はこのポリシーの下で実行しようとしています:
policy_module(httpd_php_fpm, 1.0)
require {
type unconfined_t;
type var_run_t;
type httpd_t;
type httpd_sys_content_t;
class sock_file write;
}
#============= httpd_t ==============
allow httpd_t var_run_t:sock_file write;
#doesn't work
allow httpd_t var_run_t:unix_stream_socket connectto;
#works
#allow httpd_t unconfined_t:unix_stream_socket connectto;
しかし、それはソケットへのアクセスを拒否します。
audit.log
さんのコメント:
type=AVC msg=audit(1400402777.579:642): avc: denied { connectto } for pid=11068 comm="httpd" path="/var/run/php-fpm/i10000_test-1.testtest.org.sock" scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket
type=SYSCALL msg=audit(1400402777.579:642): Arch=c000003e syscall=42 success=no exit=-13 a0=c a1=7ffe42329818 a2=32 a3=0 items=0 ppid=6136 pid=11068 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=unconfined_u:system_r:httpd_t:s0 key=(null)
そしてaudit2allow -a
は以下を生成します:
allow httpd_t unconfined_t:unix_stream_socket connectto;
ターゲットがソケットで、ソケットにtcontext=unconfined_u:unconfined_r:unconfined_t
というラベルが付いている場合、そのvar_run_t
はどこから来ますか?
Audit2allowによって「推奨」としてunconfined_t
に変更すると、機能します(上記のコメントアウト)。しかし、unconfined_t
を含むポリシーの追加を理解している限り、これは悪い考えです(必要のない多くのソケットへのアクセスを許可するためです)。
誰かが私が誤解していることを教えてもらえますか、または単に完全に間違っているだけの場合、どのように問題に対処すべきですか?
更新:わかりました。「unconfined_t」は親のphp-fpmマスタープロセスから取得されます。 .sockファイルからではありません。
ps xZ | grep php-fpm
:
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 31436 ? Ss 0:00 php-fpm: master process (/etc/php-5.3/php-fpm.conf)
これがls -Z
に反映されていない論理的な説明はありますか?
そして、これは問題が実際に悪化していることを意味しますか?つまり。 php-fpmプロセスは制限なしで実行されているため、ほとんど何でも実行できます。
更新:php-fpmをApacheと同じドメインで実行できるようにしました:
chcon system_u:object_r:httpd_exec_t:s0 /usr/php-multi/5.3.28/sbin/php-fpm
Apacheにはすでに移行ルールとselinuxポリシーが定義されているため、起動中または手動のhttpd_t
(またはrestart
の後でも、プロセスは起動するとすぐにservice php-fpm-5.3 start
ドメインに自動的に移行します)-およびPHPは、しゃっくりなしでApacheを介して実行されます。
ただし、これは(Apacheでドメインを共有する)望ましい状況(まだセキュリティの観点から)かどうかはまだわかりません。それを独自のドメインに入れようとし続け、そのためのポリシーを手動で定義する必要がありますか?
更新(私はここに新しいので、質問を更新し続けるのが不適切かどうか誰かが教えてくれますか?):
新しいタイプを作成し、php-fpmデーモンをそこで実行する方法を見つけました。ここに私の新しいポリシーがあります:
policy_module(httpd_php_fpm, 1.0)
require {
type httpd_t;
type var_run_t;
type locale_t;
type httpd_sys_content_t;
}
#============= httpd_t ==============
allow httpd_t var_run_t:sock_file write;
#============= php_fpm_t ==============
type php_fpm_exec_t;
files_type(php_fpm_exec_t);
type php_fpm_t;
files_type(php_fpm_t);
allow php_fpm_t httpd_sys_content_t:file { read getattr open ioctl append };
allow php_fpm_t locale_t:dir search;
allow php_fpm_t locale_t:file { read getattr open };
allow php_fpm_t self:capability { setuid chown kill setgid };
allow php_fpm_t self:process { signal sigkill };
allow php_fpm_t var_run_t:dir { write remove_name add_name };
allow php_fpm_t var_run_t:file { write create unlink open };
allow php_fpm_t var_run_t:sock_file { write create unlink setattr };
init_daemon_domain(php_fpm_t, php_fpm_exec_t)
ルールはaudit2allowで生成され、必要以上に許可される場合がありますが、これは機能します...もちろん、php-fpm
バイナリに新しいタイプを指定する必要があります:
chcon system_u:object_r:php_fpm_exec_t:s0 /usr/php-multi/5.3.28/sbin/php-fpm
どのソリューションが実際にセキュリティに関して最良であるかはまだわかりません。
また、一般的なアプローチに関するコメントや、このポリシーの改善の可能性についての提案も受け付けています...
これを試して
policy_module(httpd_php_fpm, 1.0)
require {
type httpd_t;
type var_run_t;
}
#============= httpd_t ==============
allow httpd_t var_run_t:sock_file write_sock_file_perms;
allow httpd_t var_run_t:unix_stream_socket client_stream_socket_perms;
## not sure what this is for but..
init_stream_connect_script(httpd_t)
[〜#〜]編集[〜#〜]
考えてみると、php-fpm
は実際にウェブサーバーの機能を実行しています。 /usr/sbin/php-fpm
と/etc/rc.d/init.d/php-fpm
をそれぞれhttpd_exec_t
とhttpd_initrc_exec_t
に設定してみてください。
ポリシーを書き換える場合は、いくつかのことを考慮する必要があります。
php-fpm
は、おそらくPHPスクリプトを実行するときにデータベースアクセスを必要とします。php-fpm
が特定のネットワークポートでリッスンすることを許可し、ApacheがUNIXソケットだけでなくそれらにも接続できるようにする必要があります。fc
ファイルを定義する必要があります。user_content
タイプのhttpdとシステムのものを読み取ることができる必要があります。実際にプログラミング言語を制限することは、多くの異なるWebアプリケーションで機能するためにポリシーがどれほど堅牢である必要があるため、かなりトリッキーになる可能性があります。
php-fpmはhttpdに該当するため、新しいタイプを作成する必要はありません。これは、php-fpmで動作し、httpdに与えるために一般的に必要な権限も持っている(RHELベースのAMI Linuxでテストされた)動作するhttpdポリシーです。
module my-httpd 1.0;
require {
type httpd_t;
type httpd_log_t;
type initrc_t;
type sysctl_vm_t;
type var_lib_t;
type var_run_t;
class unix_stream_socket connectto;
class dir { search read };
class file { write unlink };
class sock_file write;
}
#============= httpd_t ==============
allow httpd_t initrc_t:unix_stream_socket connectto;
allow httpd_t sysctl_vm_t:dir search;
allow httpd_t var_lib_t:file { write unlink };
allow httpd_t httpd_log_t:dir read;
allow httpd_t var_run_t:sock_file write;
基本的にphp-fpmが機能するために必要なのは、最後の行です(型とクラス宣言とともに)
allow httpd_t var_run_t:sock_file write;