Nginx 多虚拟主机目录隔离需配置约束、权限控制与PHP限制协同实现:各站点使用独立root路径并禁用alias逃逸,配合open_basedir硬隔离及系统用户权限加固,确保文件不可越界访问。

Nginx 实现多虚拟主机的目录隔离,核心是让每个站点的文件系统路径彼此不可见、不可越界访问。这不是靠“隐藏路径”实现的,而是通过配置约束 + 权限控制 + PHP 层级限制三者协同完成的。
用独立 root 和 location 限定静态资源范围
每个 server 块必须使用绝对路径的 root,且不能跨出该目录。Nginx 默认不校验路径合法性,所以需人工确保:
-
root /var/www/site-a;—— 所有请求都从这个目录开始解析,location /static/对应的就是/var/www/site-a/static/ - 避免使用
alias指向上级目录(如alias /var/www/;配合location /a/),容易引发路径逃逸 - 禁用
autoindex on,防止目录遍历暴露结构 - 对敏感路径显式拒绝,例如:
location ~ ^/(\.ht|\.git|\.env|config|logs) { return 403; }
配合 open_basedir 限制 PHP 文件操作边界
仅靠 Nginx 的 root 不足以阻止 PHP 脚本读写其他站点目录。必须在 PHP 层做硬隔离:
- 为每个虚拟主机启用独立的 PHP-FPM pool,每个 pool 加载专属的
php.ini或通过php_admin_value设置 - 在 pool 配置中写死
php_admin_value[open_basedir] = /var/www/site-a:/tmp - 确保
fastcgi_param PHP_VALUE "open_basedir=/var/www/site-a:/tmp";不被客户端覆盖(需配合php_admin_value使用) - 禁用
allow_url_fopen和allow_url_include,防远程文件包含
用系统用户权限进一步加固
即使配置出错,操作系统层面的权限也能兜底:
- 为每个站点创建独立系统用户(如
useradd -M -s /sbin/nologin sitea),所有文件属主设为该用户 - PHP-FPM pool 的
user和group必须匹配对应站点用户,Nginx worker 进程以www-data运行,但无权读取其他用户目录(chmod 750站点根目录,chown sitea:www-data) - 禁止所有站点用户加入
www-data组,避免组权限绕过 -
/var/www父目录设为drwxr-x---,确保各子目录相互不可进入
验证是否真正隔离
配置完成后,务必实测越界行为是否被拦截:
- 在 site-a 的 PHP 脚本中执行
file_get_contents('/var/www/site-b/config.php')→ 应报错“failed to open stream: Operation not permitted” - 尝试通过 URL 访问
http://site-a.example.com/../site-b/index.html→ 应返回 404 或 403,而非显示内容 - 检查错误日志:
tail -f /var/log/nginx/error.log和/var/log/php/error.log,确认无 open_basedir 警告被忽略


















