0

I am using Ubuntu 16.04, Apache 2.4.29 and php7.0-fpm. I am trying to create separate pools for multiple users and websites, so that they run under a separate user and each site is protected in case one is hacked. I followed the instructions of a similar post regarding this subject, but it does not quite work.

Here are two example pool.d conf files I have in /etc/php/7.0/fpm/pool.d

username1.conf

[username]
user = username1
group = username1
listen = /run/php/php7.0-fpm.username1.sock
listen.owner = www-data      #(I've already tried username1 here too)
listen.group = www-data      #(I've already tried username1 here too)
listen.mode = 0660

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

-

username2.conf

[username]
user = username2
group = username2
listen = /run/php/php7.0-fpm.username2.sock
listen.owner = www-data      #(I've already tried username2 here too)
listen.group = www-data      #(I've already tried username2 here too)
listen.mode = 0660

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

Note that I have reloaded php7.0-fpm and apache2 after each conf file saved. In addition, here are my two Apache VirtualHost files:

website1.com.conf (with username1)

<VirtualHost *:80>
  ServerAdmin admin@website1.com
  ServerName www.website1.com
  ServerAlias website1.com
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =website1.com [OR]
  RewriteCond %{SERVER_NAME} =www.website1.com
  RewriteRule ^ https://www.website1.com%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
  <IfModule mod_fastcgi.c>
    AddHandler php7-fcgi-username1 .php
    Action php7-fcgi-username1 /php7-fcgi-username1
    Alias /php7-fcgi-username1 /usr/lib/cgi-bin/php7-fcgi-username1
    FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi-username1 -socket /run/php/php7.0-fpm.username1.sock -pass-header Authorization
    <Directory "/usr/lib/cgi-bin">
      Require all granted
    </Directory>
  </IfModule>
  ServerAdmin admin@website1.com
  ServerName www.website1.com
  ServerAlias website1.com
  DocumentRoot /home/username1/website1.com
  DirectoryIndex index.html index.php
  <Directory /home/username1/website1.com>
    Options +SymLinksIfOwnerMatch
    AllowOverride None
    Require all granted
    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^website1.com
    RewriteRule (.*) https://www.website1.com/$1 [R=301,L]
    <IfModule mod_fastcgi.c>
      <FilesMatch ".+\.ph(p[3457]?|t|tml)$">
        SetHandler php7-fcgi-username1
      </FilesMatch>
    </IfModule>
  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  SSLEngine on

  <FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
  </FilesMatch>
  <Directory /usr/lib/cgi-bin>
    SSLOptions +StdEnvVars
  </Directory>
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/www.website1.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/www.website1.com/privkey.pem

website2.com.conf (with username2)

<VirtualHost *:80>
  ServerAdmin admin@website2.com
  ServerName www.website2.com
  ServerAlias website2.com
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =website2.com [OR]
  RewriteCond %{SERVER_NAME} =www.website2.com
  RewriteRule ^ https://www.website2.com%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
  <IfModule mod_fastcgi.c>
    AddHandler php7-fcgi-username2 .php
    Action php7-fcgi-username2 /php7-fcgi-username2
    Alias /php7-fcgi-username2 /usr/lib/cgi-bin/php7-fcgi-username2
    FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi-username2 -socket /run/php/php7.0-fpm.username2.sock -pass-header Authorization
    <Directory "/usr/lib/cgi-bin">
      Require all granted
    </Directory>
  </IfModule>
  ServerAdmin admin@website2.com
  ServerName www.website2.com
  ServerAlias website2.com
  DocumentRoot /home/username2/website2.com
  DirectoryIndex index.html index.php
  <Directory /home/username2/website2.com>
    Options +SymLinksIfOwnerMatch
    AllowOverride None
    Require all granted
    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^website2.com
    RewriteRule (.*) https://www.website2.com/$1 [R=301,L]
    <IfModule mod_fastcgi.c>
      <FilesMatch ".+\.ph(p[3457]?|t|tml)$">
        SetHandler php7-fcgi-username2
      </FilesMatch>
    </IfModule>
  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  SSLEngine on

  <FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
  </FilesMatch>
  <Directory /usr/lib/cgi-bin>
    SSLOptions +StdEnvVars
  </Directory>
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/www.website2.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/www.website2.com/privkey.pem
</VirtualHost>

Here is a list of all Apache mods that I have enabled:

Apache Mods Enabled

authn_core.load@                  --> /etc/apache2/mods-available/authn_core.load
authn_file.load@                  --> /etc/apache2/mods-available/authn_file.load
authz_core.load@                  --> /etc/apache2/mods-available/authz_core.load
authz_host.load@                  --> /etc/apache2/mods-available/authz_host.load
authz_user.load@                  --> /etc/apache2/mods-available/authz_user.load
autoindex.conf@                   --> /etc/apache2/mods-available/autoindex.conf
autoindex.load@                   --> /etc/apache2/mods-available/autoindex.load
deflate.conf@                     --> /etc/apache2/mods-available/deflate.conf
deflate.load@                     --> /etc/apache2/mods-available/deflate.load
dir.conf@                         --> /etc/apache2/mods-available/dir.conf
dir.load@                         --> /etc/apache2/mods-available/dir.load
env.load@                         --> /etc/apache2/mods-available/env.load
fastcgi.conf@                     --> /etc/apache2/mods-available/fastcgi.conf
fastcgi.load@                     --> /etc/apache2/mods-available/fastcgi.load
filter.load@                      --> /etc/apache2/mods-available/filter.load
headers.load@                     --> /etc/apache2/mods-available/headers.load
http2.load@                       --> /etc/apache2/mods-available/http2.load
mime.conf@                        --> /etc/apache2/mods-available/mime.conf
mime.load@                        --> /etc/apache2/mods-available/mime.load
mpm_event.conf@                   --> /etc/apache2/mods-available/mpm_event.conf
mpm_event.load@                   --> /etc/apache2/mods-available/mpm_event.load
negotiation.conf@                 --> /etc/apache2/mods-available/negotiation.conf
negotiation.load@                 --> /etc/apache2/mods-available/negotiation.load
proxy.conf@                       --> /etc/apache2/mods-available/proxy.conf
proxy.load@                       --> /etc/apache2/mods-available/proxy.load
proxy_fcgi.load@                  --> /etc/apache2/mods-available/proxy_fcgi.load
reqtimeout.conf@                  --> /etc/apache2/mods-available/reqtimeout.conf
reqtimeout.load@                  --> /etc/apache2/mods-available/reqtimeout.load
rewrite.load@                     --> /etc/apache2/mods-available/rewrite.load
security2.conf@                   --> /etc/apache2/mods-available/security2.conf
security2.load@                   --> /etc/apache2/mods-available/security2.load
setenvif.conf@                    --> /etc/apache2/mods-available/setenvif.conf
setenvif.load@                    --> /etc/apache2/mods-available/setenvif.load
socache_shmcb.load@               --> /etc/apache2/mods-available/socache_shmcb.load
ssl.conf@                         --> /etc/apache2/mods- available/ssl.conf
ssl.load@                         --> /etc/apache2/mods-available/ssl.load
status.conf@                      --> /etc/apache2/mods-available/status.conf
status.load@                      --> /etc/apache2/mods-available/status.load
unique_id.load@                   --> /etc/apache2/mods-available/unique_id.load
userdir.conf@                     --> /etc/apache2/mods-available/userdir.conf
userdir.load@                     --> /etc/apache2/mods-available/userdir.load

The problem: It seems that only one site works properly this way. A second site gets a 500 error in the browser. I'll get errors like this:

[Fri Mar 09 00:01:36.965019 2018] [fastcgi:error] [pid 31964:tid 134959322724992] (2)No such file or directory: [client ***.***.***.***:47348] FastCGI: failed to connect to server "/usr/lib/cgi-bin/php7-fcgi-username2": connect() failed
[Fri Mar 09 00:01:36.966129 2018] [fastcgi:error] [pid 31964:tid 139355612722992] [client ***.***.***.***:47348] FastCGI: incomplete headers (0 bytes) received from server "/usr/lib/cgi-bin/php7-fcgi-username2"

In addition, when I view the /var/run/php directory, I see:

php7.0-fpm.sock
php7.0-fpm.username1.sock
php7.0-fpm.pid

# (without php7.0-fpm.username2.sock)

In my "/home" directory, "www-data" is the group owner for all users and their websites:

drwx--x--- 11 username1       www-data  4096 Mar 3 07:25 username1
drwx--x--- 11 username2       www-data  4096 Mar 3 07:25 username1

Let me know where I should go from here. I'm going to have about 30 users running about 60 sites. I need Apache to run the websites as the user (instead of www-data). It needs to be done in such a way so that if a hacker breaks into a Wordpress site, they cannot use www-data to access and infect the rest of the users and their websites. If a hacker breaks in, the damage needs to be isolated to just one user.

peppy
  • 53
  • 2
  • 5

1 Answers1

1

The first line of both of your pool.d configurations is the same [username]. That's why they are treated as a single configuration and you only see /run/php/php7.0-fpm.username1.sock. Edit the first line to contain the actual username as the pool name.

Esa Jokinen
  • 43,252
  • 2
  • 75
  • 122
  • Thanks a lot! That seems to be the problem. I thought [username] was a comment or a placeholder area to let us know to put username stuff below it, I didn't realize you actually have to put your username in the square brackets []. Even though the usernames have their own socket and script is running as username, I am still having a problem with a site on one (username1) being able to access folders from another site on a different (username3), even though (username2) cannot access that file - permissions are the same for all users too. – peppy Mar 09 '18 at 21:09
  • 2
    This is the solution, nevermind the second part of my comment above. I had all of my users (except the first 2) added to the www-data unix group. After removing the users from that group and reloading php7.0-fpm, those users could no longer access each other's files. Hopefully this bit also helps someone else having the same problem. In my user directories, the folders and files still have 775 and 664 permissions and are within the www-data group. Anyone who is more knowledgeable in site security, let me know if that looks correct or not. – peppy Mar 09 '18 at 21:25