配置 PHP-FPM chroot 环境可将 PHP 进程的文件访问范围限制在指定目录内,如 /var/www/chroot,有效防止跨目录访问,但需注意 PHP 版本必须大于等于 5.3.3 才能支持相关安全特性。
原因分析
在 LNMP 环境下,PHP-FPM 与 Nginx 通过 CGI 通信,若未开启 chroot,PHP 程序的根目录默认为系统根目录 /,这意味着恶意脚本可访问 /etc/passwd、/proc 等敏感路径。根据 2016 年 5 月 30 日发布的技术文档,开启 chroot 后,即使文件实际位置是 /home/wwwroot/domain/web/index.php,经过 chroot 导向,PHP 程序中实际认为的文件地址变为 /web/index.php,实现了运行环境与系统环境的隔离。
典型报错信息如:File(/www/wwwroot/site.com/thinkphp/base.php) is not within the allowed path(s): (/www/wwwroot/site.com/public/:/tmp/),这反映了 open_basedir 与框架目录结构冲突的问题,而 chroot 提供了更底层的进程级隔离。
解决方案:建立 chroot 目录结构
以 Ubuntu 14.04.2 系统配合 ppa:ondrej/php5-5.6 提供的 PHP5.6 版本为例,执行以下命令建立基本目录结构:
mkdir -p /var/www/chroot/
cd /var/www/chroot
mkdir -p public bin dev tmp usr/sbin/ usr/share/zoneinfo/ var/run/nscd/ var/lib/php5/sessions var/www
cp -a /dev/zero /dev/urandom /dev/null dev/
chmod --reference=/tmp tmp/
chmod --reference=/var/lib/php5/sessions var/lib/php5/sessions
chown -R root:root .
chown -R www-data:www-data public/
cd var/www && ln -s ../.. chroot
其中软连接 chroot -> ../.. 用于解决 Nginx 传给 PHP-FPM 的 SCRIPT_FILENAME 在进入 chroot 后找不到文件的问题,避免访问 PHP 页面返回"File not found"错误。
解决方案:配置 PHP-FPM Pool
在 /etc/php-fpm.d/www.conf 或对应 pool 配置文件中添加以下参数:
chroot = /var/www/chroot
chdir = /public
security.limit_extensions = .php
request_terminate_timeout = 60s
request_slowlog_timeout = 3s
同时配合 open_basedir 使用,在 php.ini 或 .user.ini 中设置:open_basedir=/var/www/chroot/public/:/tmp/:/proc/,路径之间必须用英文冒号分隔,每段结尾必须带斜杠,否则 is_dir() 等函数可能失效。
解决方案:Nginx 配合配置
在 Nginx 的 PHP 配置中加入 fastcgi_param 参数,推荐使用以下组合:
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";
其中 $document_root 为 Nginx 配置项 root 对应的网站目录。/tmp/ 目录需有权限,默认存放 session 及 unixsock;/proc/ 允许 PHP 查看系统负载信息。此方法适用于各个 vhost 虚拟主机,都能限制到自己的网站目录下。
注意事项
第一,chroot 环境下需复制必要的系统库和二进制文件到 /var/www/chroot/bin 和 /var/www/chroot/usr 目录,否则依赖系统命令的 PHP 函数(如 mail()、dns 解析)会失效。2021 年 3 月 11 日的资料指出,建立合理的 PHP-FPM chroot 环境难度较大,比用 debootstrap 等工具建立还要麻烦。
第二,若使用宝塔面板,启用"防跨站攻击"后会在网站根目录自动生成 .user.ini 文件,修改前若提示"文件不可修改",先执行 chattr -i .user.ini,保存后立即执行 chattr +i .user.ini 锁定,防止被恶意脚本覆盖。
第三,cgi.fix_pathinfo 必须在 php.ini 中设置为 0,避免通过畸形路径执行非预期脚本,这是 2025 年 12 月 31 日发布的安全建议中的关键配置项。
第四,不同网站应使用各自隔离的 PHP-FPM 子进程池,实现用户级资源与权限分离,即使一个站点的 PHP 进程被劫持,也无法影响其他站点的运行上下文,此为 2026 年 3 月 15 日资料中的建议。
参考来源
来源:PHP 官方手册 - install.fpm.configuration.php 配置说明页面
来源:技术博客 - PHP-FPM 之 Chroot 执行环境详解(2016 年 5 月 30 日发布)
来源:安全配置文档 - CentOS 环境下 PHP-FPM 如何防止攻击(2025 年 12 月 31 日发布)
来源:面板配置指南 - 宝塔面板下如何设置网站的防跨站攻击隔离保护(2026 年 3 月 15 日资料)