如何在将其传递给 fastcgi 后端之前检查是否存在不可读文件?

如何在将其传递给 fastcgi 后端之前检查是否存在不可读文件?

我有几个 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被类型定义为)。当设置为其他内容(例如)时,它会尝试以一种安全的方式打开文件以防止符号链接竞争,然后对打开的文件描述符执行调用。由于 nginxstatdisable_symlinksonfstat()不能打开文件进行读取,由于没有权限,因此失败。

短期解决方案是启用符号链接再次使用disable_symlinks off,长期解决方案是修改函数以遍历包含目录,然后遍历fstatat()该目录中的文件。请记住禁用不包含 PHP 脚本但可由 PHP 用户写入的目录的符号链接。


正如所提到的http://forum.nginx.org/read.php?2,225152,234724#msg-234724,这种行为记录

在不支持仅为搜索而打开目录的系统上,使用这些参数需要工作进程对所有检查的目录具有读取权限。

我已经上传补丁这使得您可以限制符号链接,但仍然可以正常try_files工作if。另请参阅上面的链接线程。

相关内容