Назад | Перейти на главную страницу

Метка SElinux для сокетов php-fpm

Я пытаюсь настроить несколько экземпляров php-fpm для запуска нескольких версий php через apache 2.2, работающих на centos 6.5.

В какой-то момент в будущем это окажется в среде общего хостинга, поэтому мне нужна максимально возможная безопасность.

Поэтому я стараюсь вообще не отключать selinux и стараюсь установить как можно более узкие политики.

Я относительно новичок в selinux (на наших существующих серверах он просто отключен). Я много читал по этой теме, но логика все еще ускользает от меня (как я уверен, этот вопрос показывает).

При вызове php-скрипта 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?

Изменив на unconfined_t как "предложено" audit2allow, это работает (закомментировано выше). Но, насколько я понимаю, добавление политик, связанных с unconfined_t - плохая идея (так как это позволит получить доступ к множеству ненужных сокетов?)

Может ли кто-нибудь сказать мне, что я неправильно понял - или как мне подойти к проблеме, если я просто ошибаюсь?

Обновление: Хорошо, значит, «unlimited_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)

Обновление: мне удалось заставить 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 домен, как только он будет запущен, будь то во время загрузки или после ручного service php-fpm-5.3 start (или restart) - и 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 соответственно, тогда посмотрим, как это продержится.

Если вы переписываете для него политику, вам необходимо учесть ряд вещей:

  • Вероятно, вам следует убедиться, что файлы tmp имеют что-то особенное.
  • Сделайте так, чтобы php-fpm также пометил сокеты var_run и файлы pid чем-то особенным, а затем измените apache, чтобы иметь возможность подключаться к ним.
  • php-fpm вероятно, потребуется доступ к базе данных при выполнении сценариев PHP.
  • Скорее всего, вам нужно будет разрешить php-fpm чтобы прослушивать определенные сетевые порты и позволить apache подключаться к ним, а также к сокетам unix.
  • Вам нужно определить fc файл для определения контекстов файлов.
  • Убедитесь, что php-fpm может делать другие вещи, такие как imap, pop3, smtp, http, https, чтобы назвать хотя бы некоторые из них.
  • Должен иметь возможность обратной записи в содержимое httpd, где запись разрешена, и с использованием правильной метки.
  • Должен уметь читать user_content типы httpd, а также системные.

Ограничить то, что на самом деле является языком программирования, может быть довольно сложно из-за того, насколько надежной должна быть политика для работы со многими различными веб-приложениями.

php-fpm может попасть в httpd, поэтому нет необходимости создавать новый тип. Вот рабочая политика httpd, которую я написал (протестировано на AMI Linux, основанной на RHEL), которая работает с php-fpm, а также имеет обычно необходимые разрешения для предоставления 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;