我有几个 PHP 站点,我想根据权限将它们分开。因此我创建了一个新用户并为这些用户设置了一个 PHP 池。请考虑以下配置:
- PHP-FPM 以用户身份运行
php
- nginx 以用户身份运行
nginx
- webroot 是
/srv/http
,php 和 nginx 都可以访问。 - 该文件
/srv/http/index.php
可以被 php 读取,但是不是nginx 可读。 - 该文件
fastcgi_stuff
包含用于设置标头、设置后端等的基本 fastcgi 参数。假设静态文件和 PHP 文件的 webroot 相同。
下面的 nginx.conf 包含此配置的要点,它放在一个server
指令中:
server_name example.com;
root /srv/http;
index index.php;
location ~ \.php$ {
include fastcgi_stuff;
}
如果我http://example.com/
使用上述配置进行请求,页面将按预期加载。对于http://example.com/does.not.exist
,我按预期获得了 404。
为了防止将不存在的文件传递给 PHP-FPM,我尝试添加以下其中一行:
try_files $uri =404;
if ( !-e $request_filename ){ return 404; }
两者都没有像宣传的那样有效,它试图打开文件,而不是通过调用来检查是否存在stat()
。我通过检查源代码并strace
在工作进程上运行来确认这一点。
这是我遇到麻烦的一个基本情况,另一个情况是我隐藏了扩展程序,因此将 放在try_files $uri.php =404
位置块中。有什么建议吗?
答案1
Nginx 尝试打开该文件,因为我有disable_symlinks on;
。相关源代码位于 core/ngx_open_file_cache.c,函数ngx_file_info_wrapper
。(从ngx_open_cached_file
、从调用ngx_http_script_file_code
)。
如果disable_symlinks
设置为off
,nginx 会执行一个简单的 stat 调用(在 *nix 上ngx_file_info
被类型定义为)。当设置为其他内容(例如)时,它会尝试以一种安全的方式打开文件以防止符号链接竞争,然后对打开的文件描述符执行调用。由于 nginxstat
disable_symlinks
on
fstat()
不能打开文件进行读取,由于没有权限,因此失败。
短期解决方案是启用符号链接再次使用disable_symlinks off
,长期解决方案是修改函数以遍历包含目录,然后遍历fstatat()
该目录中的文件。请记住禁用不包含 PHP 脚本但可由 PHP 用户写入的目录的符号链接。
正如所提到的http://forum.nginx.org/read.php?2,225152,234724#msg-234724,这种行为记录:
在不支持仅为搜索而打开目录的系统上,使用这些参数需要工作进程对所有检查的目录具有读取权限。
我已经上传补丁这使得您可以限制符号链接,但仍然可以正常try_files
工作if
。另请参阅上面的链接线程。