Nginx 中每个虚拟主机的用户

Ale*_*hov 40 security nginx

是否可以在 nginx 中为每个虚拟主机配置不同的用户?

就像是

 server {
     user myprojectuser myprojectgroup;
     ...
 }
Run Code Online (Sandbox Code Playgroud)

Dan*_*iro 17

是的。为了额外的安全性,这是可能的,并且建议这样做(请参阅下面的原因)。

考虑到您正在使用 PHP-FPM(您可能是,因为它是最常用的),您可以为每个域创建一个由不同用户拥有的线轴。

PS:我在这里写了一个详细的分步教程:

https://learnwithdaniel.com/2019/06/user-per-virtual-host-nginx/

1. 创建线轴:

将线轴添加到每个新线轴/etc/php/7.0/fpm/pool.d/www.conf.conf为每个新线轴创建一个新文件。

线轴 #1 (myuser1):

[myprojectuser1]
user = myuser1
group = myprojectgroup
..
listen = /run/php/myuser1.sock
...  
listen.owner = www-data
listen.group = www-data
Run Code Online (Sandbox Code Playgroud)

线轴 #2 (myuser2):

[myprojectuser2]
user = myuser2
group = myprojectgroup
..
listen = /run/php/myuser2.sock
...  
listen.owner = www-data
listen.group = www-data
Run Code Online (Sandbox Code Playgroud)

PS:将您的 listen.owner/listen.group 保留给同一个 nginx 用户(通常是www-data)。

2. 将每个 spool 分配给它的服务器块(apache 用户的虚拟主机):

主机 1:

server {
  ...
  location ~ \.php$ {
    fastcgi_pass unix:/run/php/myuser1.sock;
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

主持人2:

server {
  ...
  location ~ \.php$ {
    fastcgi_pass unix:/run/php/myuser2.sock;
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

重启 FPM 和 NGINX 服务

sudo /etc/init.d/php7.0-fpm restart
sudo service nginx restart
Run Code Online (Sandbox Code Playgroud)

测试:

创建一个显示当前进程用户的pinfo.php(或任何名称)文件:

[myprojectuser1]
user = myuser1
group = myprojectgroup
..
listen = /run/php/myuser1.sock
...  
listen.owner = www-data
listen.group = www-data
Run Code Online (Sandbox Code Playgroud)

或者通过 bash创建pinfo.php文件:

echo "<?php echo str_replace(\"\\n\", '<br>', shell_exec('ps -u -p '.getmypid()));" > pinfo.php
Run Code Online (Sandbox Code Playgroud)

然后在浏览器上打开“ http://.../pinfo.php ”。


为什么要使用多个用户(安全原因):

如果您在同一用户 ( www-data )下运行所有​​网站,则PHP 调用 system()/passthru()/exec() 将可以访问所有网站!NGINX 不会保护您免受此攻击。PHP 只是一个例子,但任何流行的网络服务器语言都有类似的调用。作为黑客,您可以使用“ ls .. ”浏览所有网站,使用“ cp/echo/mv ”在任何文件(包括其他网站文件)中编写自己的代码。即使服务器上的所有网站都归同一个人(例如您)所有,也建议使用不同的用户运行每个网站,因为这会阻止最终的黑客/病毒(例如 Wordpress 病毒)访问您的其他网站。

  • 如果我理解正确: - 文件归 myuser1 所有 - PHP 池以 myuser1 身份运行 但是 nginx 呢?它仍然以用户“www-data”的身份运行。在某些情况下,这可能会导致“权限被拒绝”。该怎么办? (2认同)

wom*_*ble 8

不,因为 nginx 配置中的所有服务器节都来自同一组工作进程。此外,从安全角度来看,您最好这样运行它,因为这意味着网络服务器会自动无法写入内容(没有像 achmod -R 0777这样的愚蠢行为),因此如果 nginx 中存在漏洞,则没有内容处于危险之中。

  • 注意:如果 PHP 脚本(或 cgi-bin 进程)在 `www-data` 下运行,则每个可以提供 PHP 脚本或 cgi-bin 进程的用户都可以访问 `www-data` 用户可以访问的任何文件。对于将数据库密码存储在共享机器上的`config.php.inc` 或类似文件中的任何人来说,这似乎并不明显。 (13认同)
  • 那么没有办法对其他用户隐藏用户的文件吗?www-data 应该可以读取所有用户的内容吗? (3认同)
  • 在设置 vhost 时给文档 root 一组 `www-data` 和 perms `0710`(因为这需要 root 来配置 nginx,所以让你的自动化也设置必要的权限不是问题)。然后 docroot 的内容只需要为目录为 `o+x`,对于文件为 `o+r`。 (2认同)
  • @Ricalsin 请记住,UNIX 是一种多用户操作系统,服务器可以有多个用户。例如,`peter` 和 `john`。他们在`~/public_html` 中托管他们的网页。如果没有上面讨论这个问题的任何人提到的不同方法,.php 脚本与 web 服务器具有相同的权限,因为它也在 `www-data` 下执行。这意味着,就像 Web 服务器和 PHP 解释器一样,它可以读取任何其他 .php 脚本。 (2认同)

小智 5

为了回应上面伊万的评论,这似乎适用于 OP。两件事情:

  1. 应用程序文档根目录类似于/blah/peterWeb/html/blah/johnWeb/html。NGINX 和 Apache2 都不允许一个人在另一个目录中阅读或操作,即使它们都以组的形式运行 www-data。

  2. 将每个目录树置于他们自己的用户权限下将允许每个用户通过 ssh/登录到 UNIX 系统并保持他们的目录对每个人都是私有的 - 只是不要将每个用户放入 www-data 组。如果你同意,那么你的句子:

    每个可以提供 PHP 脚本或 cgi-bin 进程的用户都可以访问 www-data 用户可以访问的任何文件。

    可能更准确地写成:

    然后,您与 apache/nginx 服务器(www-data)放在同一组中的每个用户都可以在其可访问的任何文件中执行他们想做的任何操作(包括运行 php 脚本)(这基本上是网络上的所有内容)服务器)。

编辑 1: 必须解决一些服务器管理问题,我进一步研究了这个主题。我不知道伊万的信息有多准确!如果您打算让用户能够在共享主机配置上上传和运行脚本,那么请注意。这是一种方法。给 Ivan 的帽子提示,以确保我了解这个漏洞。

  • 不,你错过了它。PHP 脚本在 Apache 的进程(或其他 Web 服务器的)中执行时将在托管进程权限下运行。在大量幼稚的设置中,此用户是“www-data”。如果 Johnny 可以创建一个脚本并让它在 `www-data` 下运行(他可以在幼稚的设置下运行),那么 Johnny 的脚本可以读取 Peter 的脚本并将它们发送回 Johnny。这与组无关。正确的解决方案是使用 suPHP(如果设置不当,那么糟糕的代码会危及该用户的所有文件),或者监狱,或者为每个用户专门设置额外的 Web 用户。 (4认同)