nginx 中每个虚拟主机配置不同的用户是否可行?
就像是
server {
user myprojectuser myprojectgroup;
...
}
答案1
不是,因为 nginx 配置中的所有服务器节都由同一组工作进程提供服务。此外,从安全角度来看,您更好的像那样运行它,因为这意味着内容自动地不可被网络服务器写入(没有像这样的愚蠢行为chmod -R 0777
),这样如果 nginx 中存在漏洞,则任何内容都不会受到威胁。
答案2
是的。为了提高安全性,可以这样做,并且建议这样做(请参阅末尾的原因)。
我们可以使用 Nginx 的反向代理功能来实现这一点。我们在单独的进程(和用户)上运行每个主机,作为单独的 Web 服务器运行。Nginx 监视标准 HTTP 端口(80/443)并将外部请求代理到适当的主机。
在 Nginx 上实现此目的主要有两种方法:
- 代理密码:解决方案复杂,但更灵活。您为每个虚拟主机设置一个 Web 服务器实例。通常,它是使用容器(例如 docker)实现的,并设置一个 Linux 服务(systemd)来协调这一切;
- fastcgi_pass:简单易用,但每种语言的实现方式不同,且并非所有语言都支持。有局限性,但对大多数基本情况来说效果很好;
PHP
对于 PHP 用户,您可以使用 PHP-FPM 轻松实现这一点。
如果您不确定是否使用 PHP-FPM,那么您可能正在使用,因为它是 Nginx 与 PHP 的默认设置。
这个想法是创建多个“spool”,每个主机一个。然后,我们为每个spool关联一个不同的用户。
1.为每个虚拟主机创建一个用户
假设我们有虚拟主机(又称“服务器块”)mywebsite1
。其文件夹位于/var/www/mywebsite1
。
首先,我们为其创建一个新的用户和组:
adduser myuser1
此命令还创建一个同名的组(myuser1
)并将用户分配给该组。
现在,该用户应该是唯一可以访问其网站文件夹和文件的用户:
chown -R myuser1:myuser1 /var/www/mywebsite1
我不建议将用户添加到“www-data”组。
如果您需要 Nginx 访问网站文件,请参阅“Nginx 文件访问”部分了解更多详细信息和解决方案。
2. 创建线轴
打开主假脱机配置文件(例如/etc/php/7.0/fpm/pool.d/www.conf
)并为每个虚拟主机添加一个假脱机:
线轴编号 1 ( mywebsite1
):
[mywebsite1]
user = myuser1
group = myuser1
...
listen = /run/php/mywebsite1.sock
...
listen.owner = www-data
listen.group = www-data
线轴编号 2 ( mywebsite2
):
[mywebsite2]
user = myuser2
group = myuser2
...
listen = /run/php/mywebsite2.sock
...
listen.owner = www-data
listen.group = www-data
或者,您可以.conf
为每个线轴创建一个新文件。这将使文件更有条理。
listen.owner
和listen.group
必须是 Nginx 使用的同一个用户(通常是)www-data
。这并不意味着用户www-data
可以访问网站文件夹及其文件。这与套接字文件权限有关。这意味着www-data
可以向套接字文件发送 HTTP 请求。
3. 更改服务器块
将每个服务器块分配到其缓冲池。
主持人1:
server {
...
location / {
fastcgi_pass unix:/run/php/mywebsite1.sock;
}
...
}
主持人2:
server {
...
location / {
fastcgi_pass unix:/run/php/mywebsite2.sock;
}
...
}
4.重启FPM和NGINX服务
sudo /etc/init.d/php7.0-fpm restart
sudo service nginx restart
PS:“php7.0-fpm”替换为你实际的PHP-FPM。
5. 测试
创建一个pinfo.php
(或任何名称)文件来显示当前进程用户:
<?php
echo str_replace("\n", '<br>', shell_exec('ps -u -p '.getmypid()));
pinfo.php
或者通过终端创建文件:
echo "<?php echo str_replace(\"\\n\", '<br>', shell_exec('ps -u -p '.getmypid()));" > pinfo.php
然后http://.../pinfo.php
在浏览器上打开。
Nginx 文件访问
不要将用户添加到该www-data
组中。否则,这样做的目的可能落空。
控制网站的攻击者可以访问该www-data
组织拥有的文件,包括 Nginx 文件。
此外,不要将文件和文件夹的所有权更改为www-data
组。否则,获得另一台主机控制权的攻击者可以访问它们。保持它们的所有权为user:usergroup
。
Nginx 不需要直接访问网站的文件夹和文件。
允许 Nginx 直接访问文件的唯一原因是为了更优化地提供图像、视频等静态文件。
如果您想这样做,请参阅下一部分“通过 Nginx 提供静态内容”。
通过 Nginx 提供静态内容
假设出于性能原因,您允许 Nginx 访问公共静态文件。假设这些公共静态文件位于/var/www/mywebsite1/public
。
首先,为它们添加一个别名,并使“fastcgi_pass”不代理该文件夹:
server {
...
location /public {
alias /var/www/mywebsite1/public;
}
location ~ ^/public/ {
fastcgi_pass unix:/run/php/mywebsite2.sock;
}
...
}
之后,我们需要Nginx有访问文件的权限。
有以下几种选择:
www-data
1. 为用户添加网站组
使 Nginx 用户 ( www-data
) 加入网站组 ( myusergroup1
):
usermod -aG myusergroup1 www-data
这使得 Nginx 可以访问网站的文件,但反过来不行。
2.允许所有用户读取公共资产文件夹
无论如何,这些文件在互联网上都是公开可见的。
# Only do this if you don't want the previous solution
chmod -R o+r /var/www/mywebsite1/public
为什么要使用多个用户(安全原因)
假设您在同一用户下运行所有网站(例如)。在这种情况下,对//的www-data
PHP 调用将可以访问所有网站!system()
passthru()
exec()
NGINX 不会保护您免受此影响。
PHP 就是一个例子,但任何流行的 Web 服务器语言都有类似的调用。作为黑客,您可以ls ..
浏览所有网站。您可以cp
//在任何文件(包括其他网站文件)中编写代码。echo
mv
即使同一个人拥有服务器上的所有网站(例如您),也建议使用不同的用户运行每个网站,因为这样可以防止最终的黑客和病毒访问您的其他网站。
答案3
回应 Ivan 的上述评论,这似乎适用于 OP。两件事:
应用程序文档根目录类似于
/blah/peterWeb/html
和/blah/johnWeb/html
。即使 NGINX 和 Apache2 都以组的形式运行 www-data,它们都不允许其中一个目录浏览或操作另一个目录。将每个目录树置于其自己的用户权限之下将允许每个用户通过 ssh/login 进入 UNIX 系统,并将他们的目录保持为私有 - 只是不要将每个用户放入 www-data 组。如果您同意,那么您的句子:
每个可以提供 PHP 脚本或 cgi-bin 进程的用户都可以访问 www-data 用户可访问的任何文件。
可能更准确地写成:
与 apache/nginx 服务器(www-data)属于同一组的每个用户都可以在其可访问的任何文件(本质上是 Web 服务器上的所有内容)中执行任何他们想做的事情(包括运行 php 脚本)。
编辑1: 为了解决一些服务器管理问题,我进一步研究了这个主题。我不知道 Ivan 的信息有多准确!如果您打算让用户能够在共享主机配置上上传和运行脚本,那么请注意。这里是一种方法. 感谢 Ivan 帮助我理解了这个漏洞。
答案4
我自己也在寻找解决方案,并发现了两种可能的解决方法:
Nginx 的几个实例
首先,可以运行多次Nginx,每个都在不同的用户下,这确实回答了提出的问题。
当然,您需要一个主实例来监听外部接口上的 80/443 端口,并将相应的请求代理到监听不同端口(如 127.0.0.1:8001 等)的其他实例。只需为不同的用户创建不同的配置文件,然后运行多个实例即可nginx -c /path/to/config_xxx
设置正确的文件夹权限+不同的 php-fpm 用户
另一个解决方案是实际问题,“向其他用户隐藏用户文件的方法”将是丹尼尔的回答并使用户目录彼此无法访问,但允许 Nginx 进入它们。
为此,只需将用户目录保留在user:usergroup
权限下,但将www-data
用户添加到每个用户的组!通过类似 的命令usermod -a -G usergroup www-data
。这个简单(不是说 - 愚蠢)的技巧将保持用户文件夹的权限不变,但将允许 nginx 进入它们并提供静态内容。