selinux 导致 web 无法正常访问问题

服务器的架构是 lnmp(centos 6.5,nginx,mariadb,php) 当 lnmp 配置好后,访问主页时遇到,如:

CException

Application runtime path "/usr/share/nginx/html/guetoj/protected/runtime" is not valid. Please make sure it is a directory writable by the Web server process.
...

或者出现文件确实但是访问时却提示:

File not found

或者直接显示空白
在已经给这些目录 777 权限时,还是出现同样的错误,

在查看 nginx 的 errro.log 时也发现 permission deny 相关信息的提示,这时就应该是 selinux 的安全机制的限制在作用。为什么?
首选 yum 默认包中是没有包含 nginx 的,我安装时是从 nginx 官网上添加 nginx 的源后,才能用 yum 安装的。安装完,查看了 nginx 的默认 web 目录的 context type 为 system_u:object_r:usr_t:s0,
而我从其它服务上 copy 过来的文件 xxx 并不是这个 context type,所以启动 nginx 后,从浏览访问这些文件(php,html 文件)遇到无内容显示或者 file not found 等情况,
后来把这些 xxx 文件的 context type 改为

system_u:object_r:usr_t:s0

后,可以正常访问一些 html 等只需要读权限的的文件,但是 yii 的 protect/xx/runtime.php 什么的一定需要是 writable,上面改的这个 contect type 并没有让文件有写权限,所以就出现了上面所提到的明明给这些文件设置了 777 的权限,但是浏览时还是遇到 make sure xxxxi writable by xxx. 的错误提示。
一开始我想到了是 selinux 的原因,但是也做过了把 context type 修改,但是未能完全解决问题,后来我把直接把 selinux 给禁掉,命令为:

/usr/sbin/setenforce 0

关闭 SELINUX 后,嘿,网页终于能正常访问了,一点问题也没有,但是后来想想直接把 selinux 关掉,这样服务器的安全性就下降了许多,要知道如果没有开启 selinux 安全机制的 linux 与 window 处在同一层安全级别,开启了 selinux 安全机制的 linux 可要把 window(远远)甩掉好 n 层,n>=1。所以自己想想应该有办法来解决既不关掉 selinux 也可以让网页能正常被访问或者说让 nginx 能正常运行,但是自己对 selinux 并不熟悉,也 google 了一下,网上也有网友遇到类似的问题,可以通过为 nginx 添加 selinux 的白名单来解决,在写这篇文章为止自己没有仔细了解 selinux 方面的知识,当然有时间自己会去了解,也不知道怎么为某个进程或者用户添加 selinux 的白名单。
后来我发现一个快速而且能完全解决问题的方法,那就是把 web 目录下的所有文件的 context type 改为 httpd 的,为什么?
因为 apache 是直接可以通过 yum 安装的,安装后 selinux 对 apache 的安全机制已经设置好了,而我之前装过 apache(apache 运行的进程为 httpd),对于 apache 的 web 目录下的文件的 context type 为

unconfined_u:object_r:httpd_sys_content_t:s0

我尝试去把 nginx 的 web 目录的文件改为这个,所有问题都解决了。
还有如果 nginx 要访问运程 database, 则要设置,在这里我设置 nginx 的 web 文件的 contect type 为 httpd 的所以要对 httpd 相关的 selinux 模块访问开启

setsebool -P httpd_can_network_connect 1
setsebool -P httpd_can_network_connect_db 1

使用以下命令可以查看与 httpd 相关的 selinux 模块的 boolean 状态。

/usr/sbin/getsebool -a | grep httpd

参考:

http://wiki.centos.org/TipsAndTricks/SelinuxBooleans#line-44
http://www.tokiwinter.com/selinux-allowing-httpd-to-connect-to-php-fpm/
http://serverfault.com/questions/240015/how-do-i-allow-mysql-connections-through-selinux

或者直接

Google: selinux http remote access

当然,最好的方法是自己先了解 selinux,对 selinux 怎么设置,比如说怎么为 nginx 的添加 selinux 白名单,这也属于学习 linux 的一部分,一个过程。

2014-12-16