让我们看看这两个Nginx配置:
server {
listen 80;
server_name example.com;
location / {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /var/www/html/site1/i.php;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/var/www/html/site1:/tmp/:/proc/"; #禁止跨目录访问
include fastcgi_params;
}
}
server {
listen 80;
server_name example.net;
location / {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /var/www/html/site2/i.php;
include fastcgi_params;
}
}
和/srv/www/i.php
文件:
<?php phpinfo();
正如你所看到的,唯一的区别是fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/var/www/html/site1:/tmp/:/proc/"
现在,如果你重启php-fpm 和nginx,并打开example.net
,你会看到open_basedir为 no value 。在example.com会看到open_basedir
是/var/www/html/site1:/tmp/:/proc/。
但是,如果你再次访问example.net
,你会看到example.net的
open_basedir
的值也变为了 /var/www/html/site1:/tmp/:/proc/。
这会导致example.net的站点程序不正常运行。因为如果example.net的根目录不是/var/www/html/site1。所以include file时就会出错。
发生这种情况的原因很可能是“PHP设置通过PHP_ADMIN_VALUE或php_flag将覆盖其先前的值”,如PHP-FPM文档所述。
问题:如何使example.net
使用默认设置(no value)?
解决方案:
最简单的是为exmaple.net也设置PHP_ADMIN_VALUE值如 fastcgi_param PHP_ADMIN_VALUE "open_basedir=none";#不启用open_basedir或者
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/var/www/html/site2:/tmp/:/proc/";- 似乎是一个“更好”的解决方案 - 为每个站点创建单独的php-fpm进程池。
ps:
.net站没有设置PHP_ADMIN_VALUE值
。
然后,访问.com站,Nginx将传递PHP_ADMIN_VALUE值
给同一进程池中的PHP-FPM worker程序。
现在PHP-FPM进程池设置PHP_ADMIN_VALUE
为open_basedir=$document_root:/var/www/html/site1:/tmp/:/proc/
。
当再次访问.net页面时,它的open_basedir也被设置为了 $document_root:/var/www/html/site1:/tmp/:/proc/
,因为Nginx将PHP_ADMIN_VALUE
值传递到现在处理你的另一个网站的同一个进程池时它被覆盖了。
解决方案是将网站移动到另一台服务器。或者为你的站点创建一个专用的PHP-FPM进程池,这是你应该做的。
提示:
你也可以在php-fpm配置文件中配置PHP_ADMIN_VALUE,最好是在站点自己的fpm进程池配置中。
将多个站点放在一个进程池上是一个坏主意,因为我只需要让你的一个站点执行我的恶意php脚本就可以来危害所有其他使用同一个worker的站点。
注意:另外需要开启php.ini中的 opcache.validate_permission和opcache.validate_root,否则还是会不安全。
参考 为PHP-FPM和nginx设置多个进程池而安全地运行多个网站
原创文章,转载请注明:来自lenix的博客,地址 http://blog.p2hp.com/archives/5778