php-fpm 套接字的 SElinux 标签

php-fpm 套接字的 SElinux 标签

我正在尝试设置 php-fpm 的多个实例,以通过在 centos 6.5 上运行的 apache 2.2 运行多个版本的 php。

在未来的某个时候,这将最终出现在共享托管环境中,因此我需要尽可能严格的安全性。

因此,我尝试避免完全禁用 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不是一个好主意(因为它会允许访问大量不需要的套接字?)

有人能告诉我我误解了什么吗?或者,如果我完全错误地处理这个问题,我该如何处理?

更新:好的,所以'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无论是在启动期间还是在手动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

我仍然不确定哪种解决方案实际上是最安全的。

我仍然愿意听取有关总体方法的任何意见,或有关该政策的潜在改进的建议……

答案1

尝试这个

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-fpmhttpd_exec_thttpd_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_contenthttpd 的类型以及系统类型。

限制实际上的编程语言可能非常棘手,因为策略需要非常强大才能与许多不同的 Web 应用程序配合使用。

答案2

php-fpm 应该属于 httpd,因此无需创建新类型。这是我编写的可行 httpd 策略(在基于 RHEL 的 AMI Linux 上测试),它可与 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;

相关内容