Apache partilhado, com VirtualHosts, com segurança
Neste artigo, pretendo partilhar convosco, como configurar o Apache num ambiente em que o Apache é partilhado por vários sites.
Quando o Apache, é partilhado entre vários sites, de vários utilizadores, ou clientes. É necessário ter em conta, pormenores de segurança. É importante proteger os ficheiros, de cada um dos clientes. Não faz sentido, que os clientes tenham acesso endivido, ao conteúdo dos outros utilizadores.
Normalmente, isto acontece em empresas que vendem serviços de alojamento, para alojar aplicações como o WordPress, Joomla, etc.
O Apache é hoje em dia o servidor líder na web. Claro, que a qualidade e a facilidade de uso, ajudam bastante para esta liderança.
Quando é instalado, está preparado para funcionar apenas com um utilizador. Quando pretendemos que ele tenha vários “VirtualHosts“, que serão administrados por empresas ou clientes distintos, é necessário ter em conta, alguns princípios de segurança.
O Apache, tem tudo o que é necessário, para que possamos implementar vários “VirtualHosts” com segurança. Apenas, temos que fazer umas configurações.
Neste artigo, vou exemplificar a configuração do Apache, para que funcione com segurança, com vários utilizadores distintos.
Vou utilizar, o Ubuntu 14.04 Server instalado de novo e atualizado, para testar e demonstrar esta solução. Claro, que para outras distribuições, poderá ser diferente algumas configurações, no entanto, os princípios básicos, são estes para o Apache, num ambiente Linux.
Com esta configuração, pretendo separar o conteúdo dos vários “VirtualHosts“, o conteúdo estático e dinâmico. O que permite, isolar o conteúdo de cada utilizador, até mesmo em tempo de execução. Não será possível, os utilizadores terem acesso indevido aos ficheiros de outros utilizadores, até mesmo com scripts PHP. Isolando totalmente o conteúdo de todos os utilizadores.
Para que seja possível isolar todos os utilizadores, é necessário criarmos uma lógica de utilizadores, com permissões que permita isola-los.
Vamos lá então, configurar esta solução!
Neste exemplo vou criar três VirtualHosts:
- site1 – Para o web site 1
- site2 – Para o web site 2
- site3 – Para o web site 3
Cada um deles irá necessitar de um utilizador e de um grupo próprio:
- site1 – utilizador: us1 – grupo: gs1
- site2 – utilizador: us2 – grupo: gs2
- site3 – utilizador: us3 – grupo: gs3
Criar Utilizadores e Grupos
Para começar, irei criar os utilizadores e grupos necessários para esta solução.
Criar o grupo do site1:
$ sudo groupadd gs1
Criar o utilizador e indicar o grupo a que pertence, gs1:
$ sudo useradd -c "Utilizador do site1" -s /bin/false -m -d /home/us1 -g gs1 us1
Criar o grupo do site2:
$ sudo groupadd gs2
Criar o utilizador e indicar o grupo a que pertence, gs2:
$ sudo useradd -c "Utilizador do site2" -s /bin/false -m -d /home/us2 -g gs2 us2
Criar o grupo do site3:
$ sudo groupadd gs3
Criar o utilizador e indicar o grupo a que pertence, gs3:
$ sudo useradd -c "Utilizador do site3" -s /bin/false -m -d /home/us3 -g gs3 us3
Neste momento temos os utilizadores e grupos criados. Todos eles, foram criados com o seu diretório pessoal em /home.
Criar diretório para o conteúdo web
Para guardarmos de forma organizada, o conteúdo web de cada utilizador, separando de outro tipo de conteúdo, iremos criar um diretório especifico, para conteúdo web. Iremos criar o diretório “www” dentro do diretório pessoal de cada utilizador.
Para tal fazemos:
$ sudo mkdir /home/us1/www $ sudo mkdir /home/us2/www $ sudo mkdir /home/us3/www
Ajustar as permissões dos diretórios pessoais
Agora iremos ajustar as permissões do diretório pessoal, dos utilizadores, que por defeito são criadas dando a outros utilizadores permissões de leitura. E para que os utilizadores sejam completamente isolados iremos retirar a permissão aos outros utilizadores.
Para retirar as permissões aos outros utilizadores:
$ sudo chmod -R 770 /home/us1 $ sudo chmod -R 770 /home/us2 $ sudo chmod -R 770 /home/us3
Estabelecer o utilizador e grupo dos diretórios
$ sudo chown us1:gs1 -R /home/us1 $ sudo chown us2:gs2 -R /home/us2 $ sudo chown us3:gs3 -R /home/us3
Neste momento, temos todos os utilizadores e grupos, necessários para por a solução a funcionar, com segurança. Bem como, os diretórios, onde queremos alojar o conteúdo web, que cada utilizador irá partilhar na Internet.
Instalar software
Neste momento podemos começar a instalar o software necessário para o Apache. Necessitamos de instalar os seguintes pacotes:
- apache2-mpm-itk: Este modulo permite, ao apache, correr cada VirtualHost e seus processos com um utilizador independente. O que nos permite o isolamento necessário para esta solução.
- libapache2-mod-php5: Permite termos o php5 a correr no nosso servidor. O php é muito utilizado para aplicações web, é uma linguagem indispensável. E neste caso os scripts serão executados com as permissões de cada utilizador.
Para podermos instalar este software, corremos o seguinte comando:
$ sudo apt-get install apache2-mpm-itk libapache2-mpm-itk libapache2-mod-php5
Ao instalarmos, estes pacotes de software, iram ser instaladas outras dependências, inclusive, o próprio Apache.
Neste momento, temos o software necessário instalado, podemos continuar a configurar esta solução.
Configurar o Apache
Visto que optei, por criar o diretório pessoal de cada utilizador, em /home, temos que informar ao apache, para permitir servir conteúdo a partir do mesmo.
Para tal, editamos o ficheiro “/etc/apache2/apache2.conf” e adicionamos as seguintes linhas de texto. Após, as outras configurações de diretórios, para fins de organização ou no final do ficheiro.
<Directory /home/> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory>
Editar o ficheiro:
$ sudo nano /etc/apache2/apache2.conf
Neste momento, o Apache está pronto para disponibilizar conteúdo web, de cada um dos nossos utilizadores, a partir do diretório /home.
Criar os “VirtualHosts“
Agora, temos que criar os “VirtualHosts“, para cada um dos utilizadores e configura-los. Para tal, iremos criar os ficheiros em “/etc/apache2/sites-available/”. Este diretório, guarda todos os ficheiros com as configurações, dos “VirtualHosts“.
Para criar o “VirtualHost” do “site1“, editamos o ficheiro “/etc/apache2/sites-available/site1.conf” e colocamos o seguinte conteúdo:
<VirtualHost *:80> ServerAdmin root@site1 ServerName site1 DocumentRoot /home/us1/www DirectoryIndex index.php index.html index.htm ErrorLog /home/us1/error.log LogLevel warn CustomLog /home/us1/access.log combined <IfModule mpm_itk_module> AssignUserId us1 gs1 </IfModule> </VirtualHost>
Editar o ficheiro:
$ sudo nano /etc/apache2/sites-available/site1.conf
Para criar o “VirtualHost” do “site2“, editamos o ficheiro “/etc/apache2/sites-available/site2.conf” e colocamos o seguinte conteúdo:
<VirtualHost *:80> ServerAdmin root@site2 ServerName site2 DocumentRoot /home/us2/www DirectoryIndex index.php index.html index.htm ErrorLog /home/us2/error.log LogLevel warn CustomLog /home/us2/access.log combined <IfModule mpm_itk_module> AssignUserId us2 gs2 </IfModule> </VirtualHost>
Editar o ficheiro:
$ sudo nano /etc/apache2/sites-available/site2.conf
Para criar o “VirtualHost” do “site3“, editamos o ficheiro “/etc/apache2/sites-available/site3.conf” e colocamos o seguinte conteúdo:
<VirtualHost *:80> ServerAdmin root@site3 ServerName site3 DocumentRoot /home/us3/www DirectoryIndex index.php index.html index.htm ErrorLog /home/us3/error.log LogLevel warn CustomLog /home/us3/access.log combined <IfModule mpm_itk_module> AssignUserId us3 gs3 </IfModule> </VirtualHost>
Editar o ficheiro:
$ sudo nano /etc/apache2/sites-available/site3.conf
Ativar os “VirtualHosts“
Agora, que temos os “VirtualHosts” criados, para os nossos três sites, temos de ativá-los, para que o Apache possa disponibilizar o conteúdo de cada um deles.
Para ativar um “VirtualHost“, usamos o comando “a2ensite“, este comando permite ativar um “VirtualHost“.
Ativamos os nossos três desta forma:
$ sudo a2ensite site1 $ sudo a2ensite site2 $ sudo a2ensite site3
Recarregar configurações
Para que o apache, carregue os novos “VirtualHosts“, é necessário manda-lo recarregar as configurações. Da seguinte forma:
$ sudo service apache2 reload
Modificar os permissões dos ficheiros LOG
Os ficheiros error.log e access.log de cada utilizador, são criados neste caso na raiz de cada diretório pessoal. Como estes logs são criados pelo root, as permissões têm de ser modificadas, para dar acesso apenas ao dono e ao grupo. Para isso:
$ sudo chmod 660 /home/us1/*.log $ sudo chmod 660 /home/us2/*.log $ sudo chmod 660 /home/us3/*.log
Estabelecer o utilizador e grupo dos ficheiros de LOG
$ sudo chown us1:gs1 /home/us1/*.log $ sudo chown us2:gs2 /home/us2/*.log $ sudo chown us3:gs3 /home/us3/*.log
Conteúdo de teste
Neste momento, temos o nosso Apache e seus “VirtualHosts” configurados. Para que possamos verificar que esta solução funciona, temos que ter uma forma de testar, que cada utilizador só tem acesso ao seu conteúdo. Para isso, iremos adicionar um pequeno script, que irá testar e mostrar o “id” de execução, em cada requisição feita a cada um dos sites. Bem como, testar o acesso aos ficheiros dos outros utilizadores, a fim de comprovar, que não é possível ler o conteúdo dos outros “VirtualHosts“.
Iremos criar o script “index.php“, dentro do diretório “www” de cada utilizador. Este fará o trabalho por nós. Colocamos o seguinte texto em cada ficheiro:
<!DOCTYPE html> <html lang="pt"> <head> <meta charset="utf-8"> <title>Teste de permissões</title> </head> <body> <?php // Listar o "id" do utilizador e o nome com qual o script é executado // bem como o "gid" do utilizador echo "<p><b>Com que utilizador está a correr este script</b></br>"; echo system("/usr/bin/id"); echo "</p>"; //Testar se tem acesso ao ficheiro 'index.php' de cada "VirtualHost" for($x=1; $x < 4; $x++){ echo "<p><b>Acesso ao site$x</b></br>"; $ficheiro="/home/us$x/www/index.php"; if (file_exists($ficheiro)) { echo "Tem permissão de acesso ao ficheiro '$ficheiro'.</br>"; }else{ echo "Não tem permissão para aceder o ficheiro '$ficheiro'.</br>"; } } echo "</p>"; //Testar se tem acesso de leitura no ficheiro 'index.php' de cada "VirtualHost" for($x=1; $x < 4; $x++){ echo "<p><b>Acesso de leitura ao site$x</b></br>"; $ficheiro="/home/us$x/www/index.php"; if (is_readable($ficheiro)) { echo "Tem permissão de leitura no ficheiro '$ficheiro'."; } else { echo "Não tem permissão de leitura no ficheiro '$ficheiro'."; } } echo "</p>"; //Testar se tem acesso de escrita no ficheiro 'index.php' de cada "VirtualHost" for($x=1; $x < 4; $x++){ echo "<p><b>Acesso de escrita ao site$x</b></br>"; $ficheiro="/home/us$x/www/index.php"; if (is_writable($ficheiro)) { echo "Tem permissão de escrita no ficheiro '$ficheiro'."; } else { echo "Não tem permissão de escrita no ficheiro '$ficheiro'."; } } echo "</p>"; ?> </body> </html>
Editar os ficheiros “index.php”:
$ sudo nano /home/us1/www/index.php $ sudo nano /home/us2/www/index.php $ sudo nano /home/us3/www/index.php
Modificar os permissões do script “index.php“
O script index.php, de cada utilizador, foram criados como root, para evitar iniciar sessão, com cada um dos utilizadores. As permissões têm de ser modificadas, para dar permissão apenas ao utilizador e grupo. Para isso:
$ sudo chmod 660 /home/us1/www/index.php $ sudo chmod 660 /home/us2/www/index.php $ sudo chmod 660 /home/us3/www/index.php
Estabelecer o utilizador e grupo do script “index.php“
$ sudo chown us1:gs1 /home/us1/www/index.php $ sudo chown us2:gs2 /home/us2/www/index.php $ sudo chown us3:gs3 /home/us3/www/index.php
Com este tipo de configuração, é possível partilhar um servidor físico por vários sites, de forma segura e estável. Desta forma, os utilizadores só poderão trabalhar dentro do seu diretório pessoal. Evitando assim, problemas de segurança, que surgem entre sites. Bem como, acidentes esporádicos que podem acontecer, devido a anomalias inesperadas em scripts mal concebidos.
Teste
Para que possamos correr o script de teste, é necessário editar o ficheiro “/etc/hosts” de um Desktop qualquer, com Linux de preferência. Nele temos de adicionar a seguinte linha, para que possa ser possível aceder os “VirtualHosts” por um hostname. Temos de substituir o IP na linha, pelo IP real do servidor. Assim:
192.168.1.49 site1 site2 site3
Editar o ficheiro “/etc/hosts” no Linux:
$ sudo nano /etc/hosts
Neste momento está tudo configurado e pronto a ser testado, para isso utilizamos o nosso Browser preferido, o FireFox claro! Para aceder aos seguintes endereços:
http://site1
http://site2
http://site3
Se tudo correr como previsto, podemos comprovar que cada utilizador só tem permissão para aceder ao seu próprio conteúdo.
Comentem, partilhem e experimentem!