Posts com Tag ‘apache’

1) Introdução
Testamos este post na versão 7 do Debian (“wheezy”), e Mediawiki versão 1.19.20.

2)Instalar o MediaWiki (parte-1)

#apt-get install mediawiki

Esse comando instalará:
– apache2;
– mysql;
– php5;
– mediawiki,

e seus conjuntos de arquivos associados. Quando da instalação, será formulada a pergunta de qual a senha desejada para ser definida para o administrador do banco de dados MySQL (atenção: não tem nada haver com usuário root do S.O.; este usuário administrador do banco de dados será criado automaticamente na tabela mysql.user.). Veja abaixo:

Pedido de senha para usuario root MySQL

Após a execução do comando acima, o mediawiki estará disponível nas seguintes pastas (e subpastas):

  • /etc/mediawiki
  • /var/lib/mediawiki/ : contém, basicamente, links simbólicos para /usr/share/mediawiki
  • /usr/share/mediawiki/ : principal pasta. Onde estão os arquivos com o código do mediawiki

3) Uma primeira mensagem de alerta do Apache
Logo após a instalação do Apache, quando da execução do comando de recarregar a configuração do Apache (# /etc/init.d/apache2 reload) ou comando de reiniciar (# /etc/init.d/apache2 restart), uma primeira mensagem de alerta aparece:

Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName

Isso normalmente pode ser ignorado, pois não impede o bom funcionamento do Apache. Mas aquela mensagem significa que o daemon do Apache (httpd) não conseguiu obter um nome de host totalmente qualificado, fazendo uma pesquisa inversa no seu servidor de endereço IP. Uma alternativa simples para evitar estas mensagens é especificar “ServerName 127.0.0.1” no contexto do servidor global da configuração. Por exemplo, criando o arquivo /etc/apache2/conf.d/servername.local , tendo como conteúdo:

ServerName 127.0.0.1

4) Verificações básicas
a) verificar se o Apache está funcionando
Verificar se o servidor de páginas Apache está ativo, na forma exemplificada abaixo:
# ps -A | grep apache2
7561 ? 00:00:00 apache2
7706 ? 00:00:00 apache2
7707 ? 00:00:00 apache2
7708 ? 00:00:00 apache2
7709 ? 00:00:00 apache2
7710 ? 00:00:00 apache2

Acessar também a url http://localhost/ , onde uma página muito simples deverá ser mostrada no navegador, como esta abaixo (referente ao código em /var/www/index.html):
Tela inicial do Apache quando instalado

Dicas:
– para acompanhar as mensagens de erro do Apache, normalmente estas se encontram no arquivo /var/log/apache2/erro.log (quem define qual arquivo de erro é a variável ErrorLog, definida em /etc/apache2/apache2.conf).

– se desejar uma cópia local do manual da versão em uso do servidor de páginas Apache, fazer:
#apt-get install apache2-doc
Com isso, ao acessar a url http://localhost/manual/ teremos a documentação do Apache mostrada, como abaixo ilustrado:
Tela inicial do Manual do Apache

b) verificar se o PHP está funcionando
Criar o arquivo /var/www/index.php com o seguinte conteúdo:

<?php
phpinfo();
?>

Reiniciar o Apache:
# /etc/init.d/apache2 restart

Agora, acessar o endereço http://localhost/index.php . Se as informações de configuração do PHP aparecerem, isto significará que o Apache e o interpretador PHP foram instalados corretamente e estão funcionando. Veja um exemplo de um pedacinho da página que deverá ser mostrada:

Tela de teste do funcionamento do interpretador PHP

c) verificar se o MySQL está funcionando.
Verificar se o processo MySQL server foi iniciado e está “ativo”:

$ ps -A | grep mysql
7391 ?        00:00:00 mysqld_safe
7720 ?        00:00:13 mysqld

Para ter acesso ao banco do MySQL, utilizar o seguinte comando:
$ mysql -u root -p
Este comando é destinado a fazer a autenticação no banco de dados MySQL. Será solicitado a senha do usuário “root” (que neste momento é o usuário administrador do MySQL) de acesso ao banco que fora definida anteriormente na instalação. Forneça a senha, conforme definida naquele momento da instalação.

Dicas:
– verificar se o servidor MySQL está instalado e qual a sua versão: $ apt-cache policy mysql-server
– verificar se o client MySQL está instalado e qual a sua versão: $ apt-cache policy mysql-client
– estando autenticando do servidor MySQL, são úteis os seguintes comandos básicos:
* status do banco: mysql> status;
* base de dados existentes: mysql> show databases;
* selecionar uma base de dados (exemplo: a BD mysql): mysql> use mysql;
* listar as tabelas de uma BD (que fora anteriormente selecionada): mysql> show tables;
* verificar os usuários existentes:


mysql> SELECT User, Host, Password FROM mysql.user;
+------------------+-----------+-------------------------------------------+
| User             | Host      | Password                                  |
+------------------+-----------+-------------------------------------------+
| root             | localhost | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| root             | 127.0.0.1 | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| root             | ::1       | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| debian-sys-maint | localhost | *BEB671E4F154411B71BEEDA86385600449ED3346 |
+------------------+-----------+-------------------------------------------+

Neste caso, fora o próprio sistema operacional, apenas usuário do BD chamado “root” pode ter acesso, fornecendo senha, e partindo do própria máquina.
* para outros comandos do BD MySQL veja o post Tutorial MySQL.

5) Instalar o MediaWiki (parte-2)
5.1 Liberar acesso inicial para parametrizar o mediawiki
Editar o arquivo da configuração do Apache em /etc/mediawiki/apache.conf e remover o sinal de comentário ‘#’ presente na sua terceira linha, ficando desta forma:
Alias /mediawiki /var/lib/mediawiki
Reiniciar o Apache:
# /etc/init.d/apache2 restart

Obs: observar que existe o arquivo /etc/apache2/conf-available/mediawiki.conf com as diretivas de configuração para o Apache achar o mediawiki.

Nesse momento, já é possível acessar a página inicial do Mediawiki para iniciar seu processo de configuração. Ao acessar a url http://localhost/mediawiki/ a seguinte página deverá ser mostrada:
Tela inicial do Midiawiki, para iniciar sua configuração

5.2 Iniciar a parametrização do mediawiki
Clicar no link mostrado na figura anterior e iniciar a parametrização do Mediawiki. Algumas dicas úteis:
– nome do utilizador da base de dados: informar o nome do usuário já criado na BD do MySQL que será usado para ter acesso à BD durante o processo de instalação. Este usuário não é o do MediaWiki, e sim de um usuário da base de dados.
– conta de administrador, seu nome: o seu nome, por exemplo, “Joao Beltrao”. Este é o nome que irá utilizar para entrar na wiki.
– sobre o arquivo LocalSettings.php: automaticamente será gerado um arquivo de configuração que será disponibilizado ao usuário que está instalando o mediawiki. Salve este arquivo e coloque-o na mesma pasta do arquivo index.php do mediawiki (no caso deste post, esta pasta após iniciar os dois links simbólicos é a /etc/mediawiki/ .

Pronto, acesse a url http://localhost/mediawiki/ e observe que o Mediawiki estará funcionando normalmente. Faça o login através do usuário que fora criado (no caso, “Joao Beltrao”). Bom uso.

5.3 Parametrizações do arquivo LocalSettings.php
Este arquivo permite um grande número de parametrizações. Algumas dicas (no caso, acrescentar ao final do arquivo as seguintes linhas:
$wgGroupPermissions['*']['edit'] = false;
$wgLocalTZoffset = -180;
$wgGroupPermissions['*']['createaccount'] = false;

A primeira linha acima serve para evitar que usuários anônimos possam modificar o conteúdo do Wiki; a segunda linha para que o Wiki utilize o mesmo fuso horário do usuário no momento de uma edição (horário brasileiro: -3 horas = -180 minutos); a terceira linha desabilita a criação de novos usuários pelos próprios internautas, tarefa que será feita exclusivamente pelo administrador do wiki.

Se desejar, fazer:
$wgGroupPermissions['*']['read'] = false;
Com isso, só é permitido a leitura do wiki por usuários logados no wiki.

Obs: o logo do wiki é definido pela variável “$wgLogo” que por padrão está apontando para /usr/share/mediawiki/skins/common/images/wiki.png. Recomenda-se que se utilize uma figura com fundo transparente de 135×135 pixels. Uma rápida modificação dessa imagem visualizada nesta instalação, apenas altere o valor da variável “$wglogo” que está apontando para a imagem “wiki.png”, deixando-a apontando para a imagem “mediawiki.png” (que está na mesma pasta).

5.4 Dica de segurança
Caso o mediawiki for instalado em uma área pública, cuidado deve-se ter quanto a proibição do acesso de usuários ao arquivo de configuração. Assim, quando for esse o caso, a alteração da permissão do arquivo /etc/mediawiki/LocalSettings.php seria recomendável:

# chmod 600 LocalSettings.php
# chown www-data:www-data LocalSettings.php

Isto fará com que este arquivo não fique visível a outros usuários. É uma medida de segurança.
Se a configuração de segurança fora feita com sucesso, ao acessar a url http://localhost/mediawiki/LocalSettings.php uma página em branco ou uma página de erro deve ser mostrada.

5.5 Uma verificação da base de dados após mediawiki estar instalado
Para isso, faça a autenticação na base de dados. Assim:
a) verificar as bases de dados
Caso o nome da base de dados escolhida na instalação do wiki tenha sido “my_wiki”, tem-se:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| my_wiki            |
| mysql              |
| performance_schema |
+--------------------+

b) verificar as tabelas criadas para o wiki
Após chavear para a base de dados “my_wiki”, e durante a instalação do wiki escolheu-se “prefixo” para o nome dos prefixos das tabelas relativas as bases de dados do wiki, tem-se:

mysql> show tables;
+---------------------------+
| Tables_in_my_wiki         |
+---------------------------+
| prefixoarchive            |
| prefixocategory           |
| prefixocategorylinks      |
| prefixochange_tag         |
          .
          .
          .

5.6 Testar o funcionamento do mediawiki como um todo
Agora que o mediawiki está instalado, é hora de testar os passos executados. Pelo menos, teste as seguintes facilidades:

– edição de página;
– criação de página;
– criação de usuário.

5.7 Acessar o Mediawiki de outras máquinas
Para isto, basta alterar o valor da variável wgServer do arquivo LocalSettings.php: em vez de localhost (que é o default), coloque o IP de sua máquina. Exemplo:
$wgServer ="http://192.167.34.25";

6) Dicas adicionais para aqueles que desejam criar um domínio próprio para o wiki
A partir desse ponto, são dicas adicionais e não há obrigatoriedade de seguir para deixar o Mediawiki funcionando.

Copiar os apontadores do Mediawiki (e mais algumas pastas adicionais) para o diretório raiz do Apache

# cp -a /var/lib/mediawiki/ /var/www/wiki

6.1) Preparar o ambiente antes de continuar a instalação do Mediawiki

6.1.1) escolher um nome de domínio para acessar o mediawiki. Por exemplo: http://www.meuwiki.com
6.1.2) criar uma entrada no Apache para o novo domínio meuwiki
a) Criar um arquivo em /etc/apache/sites-available, por exemplo de nome ‘meuwiki’, com o seguinte conteúdo:

<VirtualHost *:80>
ServerName http://www.meuwiki.com
DocumentRoot /var/www/wiki
</VirtualHost>

obs: para facilitar, faça uma cópia do arquivo ‘default’ para o ‘meuwiki’, e edite suas diretivas.

b) Habilitar o dominio virtual

#a2ensite meuwiki

c) caso o novo domínio esteja hospedado na mesma máquina que o usuário esteja usando, crie uma entrada em /etc/hosts:

127.0.0.1 http://www.meuwiki.com

6.2) Recarregar o Apache com as novas configurações

# /etc/init.d/apache2 reload

6.3) Complementar a instalação do Mediawiki pelo navegador
Na caixa de endereços de URL do navegador, digitar o endereço do Mediawiki e complementar sua instalação. O acesso ao Mediawiki deve ser pelo nome do domínio escolhido (isso é MUITO IMPORTANTE!!!, para que a instalação fique correta e o Mediawiki acessível de qualquer máquina da rede):

http://www.meuwiki.com

A tela mostrada é para iniciar a configuração do Mediawiki, pois ainda o arquivo de configuração LocalSettings.php ainda não fora criado na pasta /etc/mediawiki/. Este arquivo será criado quando for terminado o processo de complementação da instalação do mediawiki, realizado pelo usuário com o navegador clicando no hiperlink “Set up the wiki” (conforme figura anterior).

6.4) Setup do Wiki
Um exemplo de setup do wiki:

Wiki name: “Meuwiki”
Admin username: “wikiadmin”
Password: <senha_do_wikiadmin>
Databasehost: “10.200.70.5:3306” ou “localhost” (se base dados em outra máquina ou na mesma em que fora instalado o wiki, respectivamente)
DB name: “db_meuwiki”
DB username: “adm_wiki”
DB password: <senha do DB admin>
Database table prefix: “meuwiki_”
Storage Engine: “InnoDB”
Database character set: “MySQL4.1/5.0 UTF-8”

Após executar este “setup”, será criado o banco de dados “db_meuwiki“, e a tabela “mysql.user” terão os seguintes usuários criados:

User Host Password
adm_wiki % *07C2A823749F8D68A9758F74DDDC945DE57873F6
adm_wiki localhost *07C2A823749F8D68A9758F74DDDC945DE57873F6
adm_wiki localhost.localdomain *07C2A823749F8D68A9758F74DDDC945DE57873F6

 

6.5) Disponibilizar o arquivo LocalSettings.php gerado na sua pasta definitiva
Após ter clicado no link “set up the wiki”, conforme mostrado na figura acima, respondido as questões apresentadas pelo aplicativo e, ao final, ter obtido uma mensagem de sucesso, complemente a instalação do Mediawiki disponibilizando este arquivo na sua pasta definida (a mesma que contém o arquivo com o código inicial do midiawiki – “index.php”). Na instalação exemplificada neste post, a pasta seria /var/lib/mediawiki:

# mv LocalSettings.php /var/lib/LocalSettings.php

Agora, garanta a segurança necessária ao ambiente:
# chmod 600 /var/lib/LocalSettings.php
# chown root:root /var/lib/LocalSettings.php

Links uteis:
1- Instalação do MediaWiki em sites pessoais em WebHostings
2- Instalação do MediaWiki no Debian Etch
3- Instalação do MediaWiki em sites pessoais em WebHostings
4- Instalando Apache+PHP+MySQL no Linux/Debian
5- Tutorial MySQL ( instalar em ambiente Linux – Debian )
6- Configurar domínios virtuais do Apache em máquina Linux/Debian
7- Instalar e configurar Módulos do Apache2 no Debian

1. Por que da necessidade de um proxy?

Todos os navegadores modernos impõem uma restrição de segurança em conexões de rede, que inclui chamadas para XMLHttpRequest. Esta restrição impede que um script (ou aplicativo) de fazer uma conexão com qualquer servidor web que não seja o do próprio domínio de onde fora carregado (Internet Explorer permitirá solicitações entre domínios se a opção tiver sido ativada nas preferências). Se tanto a aplicação web e os dados XML que usa aplicativos vêm diretamente do mesmo domínio, então não haverá qualquer restrição e solicitações de dados podem ser realizadas livremente. Ou seja, quando um código JavaScript está carregando dados HTML, XML ou JSON de um recurso no mesmo domínio, tudo que é necessário é solicitar normalmente (de forma direta) estes dados. Observe a figura a seguir.

Solicitação de dados do mesmo servidor: sem necessidade de proxy.

Se, entretanto, a aplicação web é carregada de um determinado domínio web e esta aplicação faz solicitações de dados de serviços da Web de outro domínio, o navegador do usuário impedirá que a conexão seja aberta. Pode ser uma chatice a princípio, mas isto se justifica por questões de segurança. Observe a figura a seguir.

Solicitação de dados de outro host: necessidade de proxy.

Há uma série de soluções para esta situação, mas o mais comumente usado é a instalação de um proxy no próprio servidor web de onde a aplicação fora carregada. Em vez de fazer chamadas XMLHttpRequest diretamente para o serviço web, se faz as chamadas para o proxy do servidor web do domínio da aplicação. O proxy, em seguida, passa a chamada para o serviço web no host destino e, em contrapartida, passa os dados para o aplicativo cliente quando estes forem respondidos. Como a conexão é feita para o servidor da aplicação, e os dados de volta provêm do servidor da aplicação, o navegador não tem nada a reclamar. Observe a figura abaixo.

Solicitação de dados de outro servidor: proxy funcionando.

Conclusão: é necessário ter um web proxy funcionando para ultrapassar as limitações de segurança do Javascript quando se tem que requisitar dados de um servidor diferente daquele da aplicação.
OBS:
Mais rigorosamente, a origem de uma página é definida por seu protocolo, host e porta. Por exemplo, a origem da página deste post é (‘http’,’concani3.wordpress.com’, 80).

2. Um simples web proxy em Python para uso com a biblioteca OpenLayers
Vamos mostrar neste post a superação da restrição “cross-domain” através de um simples script com função Proxy, escrito em Python. Isto irá fazer com que o código JavaScript da aplicação possa acessar conteúdos de webpages de outros domínios, superando estas limitações de segurança “cross-domain”. É necessário para isto instalar este script no servidor de onde é carregado a aplicação JavaScript.

2.1 Disponibilizar o script que implementa o proxy
No caso da bilbioteca OpenLayers-2.12, esta traz uma sugestão de script em Python para funcionar como um proxy. Esse script é encontrado em OpenLayers-2.12/examples/proxy.cgi. Há a necessidade de alterar apenas uma instrução deste arquivo: incluir o nomes dos domínios destino (ou dos dominios destinos) no array “allowedHosts”. E nada mais. Por exemplo, se houvesse a necessidade de requisitar dados dos dominios http://www.exemplo1.com.br e de http://www.exemplo2.com.br, a configuração ficaria assim:
allowedHosts = ['www.exemplo1.com.br', 'www.exemplo2.com.br']

Vamos disponibilizar este arquivo numa pasta tradicionalmente comum para scripts cgi: em /usr/lib/cgi-bin. Assim, fazer:

# cp pasta_do_OpenLayers/OpenLayers-2.12/examples/proxy.cgi /usr/lib/cgi-bin/.

OBS:
– se a pasta destino cgi-bin não estiver criada, faça sua criação;
– por padrão, o interpretador Python em máquinas Linux já vem instalado. Portanto, nada a se preocupar quanto a este aspecto.

2.2 Código do web proxy
Por conveniência, vamos disponibilizar aqui este código do web proxy fornecido pela biblioteca OpenLayers:


#!/usr/bin/env python

import urllib2
import cgi
import sys, os

# Designed to prevent Open Proxy type stuff.

allowedHosts = ['www.openlayers.org', 'openlayers.org', 
                'labs.metacarta.com', 'world.freemap.in', 
                'prototype.openmnnd.org', 'geo.openplans.org',
                'sigma.openplans.org', 'demo.opengeo.org',
                'www.openstreetmap.org', 'sample.azavea.com',
                'v2.suite.opengeo.org', 'v-swe.uni-muenster.de:8080', 
                'vmap0.tiles.osgeo.org', 'www.openrouteservice.org',
                'maps.wien.gv.at','www.exemplo1.com.br','www.exemplo2.com.br']

method = os.environ["REQUEST_METHOD"]

if method == "POST":
    qs = os.environ["QUERY_STRING"]
    d = cgi.parse_qs(qs)
    if d.has_key("url"):
        url = d["url"][0]
    else:
        url = "http://www.openlayers.org"
else:
    fs = cgi.FieldStorage()
    url = fs.getvalue('url', "http://www.openlayers.org")

try:
    host = url.split("/")[2]
    if allowedHosts and not host in allowedHosts:
        print "Status: 502 Bad Gateway"
        print "Content-Type: text/plain"
        print
        print "This proxy does not allow you to access that location (%s)." % (host,)
        print
        print os.environ
  
    elif url.startswith("http://") or url.startswith("https://"):
    
        if method == "POST":
            length = int(os.environ["CONTENT_LENGTH"])
            headers = {"Content-Type": os.environ["CONTENT_TYPE"]}
            body = sys.stdin.read(length)
            r = urllib2.Request(url, body, headers)
            y = urllib2.urlopen(r)
        else:
            y = urllib2.urlopen(url)
        
        # print content type header
        i = y.info()
        if i.has_key("Content-Type"):
            print "Content-Type: %s" % (i["Content-Type"])
        else:
            print "Content-Type: text/plain"
        print
        
        print y.read()
        
        y.close()
    else:
        print "Content-Type: text/plain"
        print
        print "Illegal request."

except Exception, E:
    print "Status: 500 Unexpected Error"
    print "Content-Type: text/plain"
    print 
    print "Some unexpected error occurred. Error text was:", E

 
2.3 Configurar o Apache
Vamos fazer aqui uma configuração muito simples do Apache, sem lançar mão de criação de “Virtual Hosts”. Editar o host virtual default, criado quando da instalação do Apache, o 000-default:
Editar /etc/apache2/sites-enabled/000-default, alterando algumas de suas linhas:


    # Para poder executar a chamada proxy pela instrução:
    # OpenLayers.ProxyHost = "/cgi-bin/proxy.cgi?url=";
	ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
	<Directory "/usr/lib/cgi-bin">
		AllowOverride None
		Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
		Order allow,deny
		Allow from all
        </Directory>

 
Reiniciar o Apache:
# /etc/init.d/apache2 restart

2.4 Testar o funcionamento do web proxy
Para verificar o funcionamento do proxy, dois testes muito simples podem ser realizados.

a) Primeiro teste
Na barra de endereços do navegador, digitar o endereço do proxy passando como parâmetro um endereço que consta em “allowedHosts”. Por exemplo, o endereço openlayers.org. Fazer assim:
http://nome-servidor-do-proxy/cgi-bin/proxy.cgi?url=http://openlayers.org

Deve ser mostrado a página inicial do OpenLayers, solicitada através do proxy.

b) Segundo teste
Na barra de endereços do navegador, digitar o endereço do proxy passando como parâmetro um endereço que NÃO consta em “allowedHosts”. Por exemplo, o endereço uol.com.br. Fazer assim:
http://nome-servidor-do-proxy/cgi-bin/proxy.cgi?url=http://uol.com.br

Uma mensagem de negação do proxy deve ser mostrada na tela. Algo assim:


This proxy does not allow you to access that location (uol.com.br).

{'HTTP_COOKIE': '__utma=145174525.209261312.1401672948.1401672948.1401672948.1;
 __utmb=145174525.1.10.1401672948; __utmc=145174525; __utmz=145174525.1401672948.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)',
 'SERVER_SOFTWARE': 'Apache', 'SCRIPT_NAME': '/cgi-bin/proxy.cgi', 'SERVER_SIGNATURE': '', 'REQUEST_METHOD': 'GET',
 'SERVER_PROTOCOL': 'HTTP/1.1', 'QUERY_STRING': 'url=http://uol.com.br', 'PATH': '/usr/local/bin:/usr/bin:/bin',
 'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20131030 Firefox/17.0 Iceweasel/17.0.10',
 'HTTP_CONNECTION': 'keep-alive', 'SERVER_NAME': 'nome-servidor-do-proxy', 'REMOTE_ADDR': 'IP_do_navegador_usuario',
 'SERVER_PORT': '80', 'SERVER_ADDR': 'nome-servidor-do-proxy', 'DOCUMENT_ROOT': '/var/www',
 'SCRIPT_FILENAME': '/usr/lib/cgi-bin/proxy.cgi', 'SERVER_ADMIN': 'webmaster@localhost', 'HTTP_HOST': 'nome-servidor-do-proxy',
 'REQUEST_URI': '/cgi-bin/proxy.cgi?url=http://uol.com.br', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
 'GATEWAY_INTERFACE': 'CGI/1.1', 'REMOTE_PORT': '6315', 'HTTP_ACCEPT_LANGUAGE': 'pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3',
 'HTTP_ACCEPT_ENCODING': 'gzip, deflate'
}

 
2.5 Definição do web proxy na aplicação
Estando o web proxy funcionando, na aplicação JavaScript que utiliza a bilbioteca OpenLayers basta inserir a definição do ProxyHost:

OpenLayers.ProxyHost = "/cgi-bin/proxy.cgi/?url=";

Referências:
1- JavaScript: use a Web Proxy for Cross-Domain XMLHttpRequest Calls
2- Same-origin policy
3- Cross-Domain requests in Javascript
4- Same-origin policy
5- In which ways could a javascript making a cross domain HEAD request be a threat?
6- W3C – Cross-Origin Resource Sharing

1. Introdução
Um servidor Web pode dar suporte a vários sites.  Cada um destes sistes é identificado com uma diretiva de container <VirtualHost>.  No Apache existem dois tipos diferentes de host virtual suportados:
a) host virtual baseado em nome    (name-based) – onde mais um host virtual roda no mesmo endereço IP, mas com nomes diferentes;
b) host virtual baseado em IP (IP-based)     –  cada host virtual possui o seu próprio endereço IP.

Em ambos os casos, os endereços IP compartilhados pelos diversos hosts virtuais do Apache precisam ser declarados com uma diretiva NameVirtualHost.

Hosts virtuais name-based é geralmente mais simples, já que você só precisa configurar o servidor DNS para mapear cada nome de host para o endereço IP correto e, em seguida, configurar o Apache HTTP Server para reconhecer os diferentes nomes de host.

2. Diretivas Apache
Uma diretiva é apenas permitida dentro de um contexto designado. Se o usuário tentar usá-la em qualquer outro contexto , será emitida uma mensagem de erro de configuração que evitará o servidor de tratar as requisições naquele contexto , ou até mesmo evitará o servidor de iniciar.  Ou seja, as diretrizes de configuração só adquirem validade dependendo do contexto em que são aplicadas:

a) server config: este contexto são encontrados nos arquivos de configuração do servidor (por exemplo, em /etc/apache2/apache2.conf).  Para ter validade, as diretivas NÃO podem ser utilizadas dentro de qualquer container <VirtualHost> ou <Directory>. Também não pode ser utilizada dentro de arquivos .htaccess. São diretivas que controlam o funcionamento dos processos do servidor Apache como um todo, afetando a operação global do Apache, como o número de solicitações simultâneas que ele pode manipular ou onde ele pode encontrar seus arquivos de configuração. Exemplos destes tipos de diretivas: ServerRoot, LockFile, PidFile, KeepAlive, StartServers, StartServers, etc.

b) virtual host:  este contexto significa que a diretiva pode aparecer dentro de containers <VirtualHost> nos arquivos de configuração do servidor. São diretivas que afetam a configuração de apenas parte do servidor, e que não estão associdas ao escopo de um host virtual em particular.

c) directory: uma diretiva marcada como sendo válida neste contexto deve ser utilizada dentro dos containers <Directory>, <Location>, <Files>, e <Proxy> nos arquivos de configuração do servidor, sujeita as restrições descritas nas Seções de Configuração.

d).htaccess:  se uma diretiva é válida neste contexto, ela significa que pode aparecer dentro de arquivos .htaccess per-directory. Ela pode não ser processada, dependendo das substituições ativas no momento.

A localização válida para a diretiva são resultado de um OR booleano de todos os contextos listados. Em outras palavras, uma diretiva que está marcada para ser válida em “server config” e “.htaccess” pode ser utilizada no arquivo apache2.config e nos arquivos .htaccess, porém não dentro dos containers <Directory> ou <VirtualHost>.

É importante entender que o arquivo de configuração do Apache é lido de cima para baixo.  Arquivos que usam “include” são considerados como aparecendo inteiramente na localidade onde aparece a diretiva Include. Assim, se existir uam mesma diretiva aparecendo duas vezes, mas com valores diferentes, a que vir por último será a que realmente terá efeito. Deve ser considerado também os arquivos .htaccess, os quais são capazes de substituir as configurações do arquivo de configuração principal do servidor Apache. Uma outra situação, é entender como funcionam as diretivas com relação aos subdiretórios.  Por exemplo:

<Directory /www/site1>
    Options ExecCGI
</Directory>
<Directory /www/site1/html>
    Options Includes
</Directory>

No exemplo acima, os arquivos acessados a partir do diretório /www/site1/html/misc/ terão “Options Includes” ativada, mas não “Options ExecCGI”, porque a seção com a especificação mais específica é que se aplica.

2.1 Algumas diretivas especiais
a) NameVirtualHost
Manual: http://httpd.apache.org/docs/2.2/mod/core.html#namevirtualhost
Descrição: designa um endereço IP para name-virtual hosting
Syntaxe:    NameVirtualHost addr[:port]
Contexto:    server config

b) <VirtualHost>
Manual: http://httpd.apache.org/docs/2.2/mod/core.html#virtualhost
Descrição:    contém diretivas que se aplica apenas para um hostname específico ou endereço IP
Syntaxe:    <VirtualHost addr[:port] [addr[:port]] …> … </VirtualHost>
Contexto:    server config


3. Configurar hosts virtuais baseados em nome

Para usar name-based virtual hosting, você deve designar o endereço IP (e possivelmente a porta) no servidor que estará aceitando pedidos para os hosts. Isso é configurado usando a diretiva NameVirtualHost. No caso normal onde deve ser usado todas e quaisquer endereços IP no servidor, você pode usar * como o argumento para NameVirtualHost. Se você estiver planejando usar múltiplas portas (por exemplo, executando SSL), você deve adicionar uma porta para o argumento, como *:80. Note-se que mencionar um endereço IP em uma diretiva NameVirtualHost não faz automaticamente o servidor ouvir o endereço IP. Além disso, qualquer endereço IP especificado aqui deve ser relacionado com uma interface de rede no servidor.

O próximo passo é criar um bloco <VirtualHost> para cada host que você gostaria de servir. O argumento para a diretiva <VirtualHost> deve coincidir com a definida pela diretiva NameVirtualHost. (Neste caso, é habitual usar “*:80” ). Dentro de cada bloco <VirtualHost> , você vai precisar no mínimo de uma directiva ServerName para designar qual é o host servido e uma diretiva DocumentRoot para mostrar onde no sistema de arquivos o conteúdo para aquele host reside.

a) Exemplo de hosts virtuais baseados em nome

ServerName    127.0.0.1
NameVirtualHost    *:80
<VirtualHost    *:80>
    ServerName    sitio1.com.br
    DocumentRoot    /var/www/sitio1
</VirtualHost>
<VirtualHost    *:80>
    ServerName    sitio2.com.br
    DocumentRoot    /var/www/sitio2
</VirtualHost>

Algumas explicações para o exemplo acima:
i)  NameVirtualHost    *:80        – os hosts especificados rodam em todos os endereços, acessados via porta 80
ii) ServerName    127.0.0.1    – os hosts todam também no endereço de loopback (localhost).  Ou seja, se o usuário estiver na própria máquina que está servindo de servidor físico poderá visualizar os sítios.

OBS:
i)  o argumento para a diretiva <VirtualHost> necessita ser idêntico àquele presente na diretiva NameVirtualHost.
ii) atenção: as requisições para as quais não houver um host virtual listado irão para o primeiro vhost listado no arquivo de configuração.  No caso do exemplo acima, as requisições que chegarem ao servidor usando nomes de hosts que não estejam mencionados explicitamente em um dos hosts virtuais serão atendidas pelo host virtual sitio1.com.br
iii) é possível associar vários nomes a um determinado host virtual através da diretiva ServerAlias:

ServerName    sitio2.com.br
ServerAlias    www.sitio2.com.br sitio2.info www.sitio2.info

b) Designando um host visual baseado em nome como padrão
É recomendável que seja direcionado a um host padrão todas aquelas requisições não atendidas independentemente delas especificarem um nome ou usarem um endereço IP.  Esse host padrão poderia mostrar uma página de erro, por exemplo, com uma mensagem de erro “host não encontrado”.

Para isto, adicionar a seguinte seção <VirtualHost> antes de qualquer outro (esta ordem é fundamental!!!):

<VirtualHost    *:80>
    ServerName    default
    DocumentRoot    /var/www/htdocs
    ServerDocument    404    /site_list.html
</VirtualHost>


4. Configurar hosts virtuais baseados em endereço IP

Uma situação comum neste tipo de configuração é ter diversos endereços IP e desejar um site em cada endereço.  Veja o exemplo a seguir:

a) Exemplo de hosts virtuais baseados em IP

ServerName    127.0.0.1
<VirtualHost    10.0.0.1>
    ServerName    sitio3.com
    DocumentRoot    /var/www/sites/sitio3
</VirtualHost>
<VirtualHost    10.0.0.2>
    ServerName    sitio4.com
    DocumentRoot    /var/www/sites/sitio4
</VirtualHost>

Algumas explicações para o exemplo acima:
Os hosts virtuais definidos acima capturam todas as requisições destinadas aos endereços IP especificados, independentemente de qual nome de host esteja sendo usado para se chegar lá.  Requisições destinadas a qualquer outro endereço IP não listado vão para o virtual host incluído no corpo principal do arquivo de configuração (servidor “padrão”).  O ServerName especificado é usado como o nome primário do host virtual, quando necessário, mas não é usado no processo de mapear uma requisição ao host correto.  Apenas o endereço IP (e não o campo Host do cabeçalho) é consultado para se descobrir qual virtual host deve atender à requisição.


5. Misturando hosts virtuais baseados em endereço e baseados em nome

Uma situação que pode acontecer é a existência de vários endereços IP atribuídos ao sistema e se deseja ter mais de um sitio em cada endereço.  Veja o exemplo abaixo:

ServerName    127.0.0.1
NameVirtualHost    10.0.0.1:80
NameVirtualHost    10.0.0.2:80

<VirtualHost    10.0.0.1:80>
    ServerName    sitio5.com
    DocumentRoot    /var/www/sites/sitio5
</VirtualHost>
<VirtualHost    10.0.0.1:80>
    ServerName    sitio6.com
    DocumentRoot    /var/www/sites/sitio6
</VirtualHost>
<VirtualHost    10.0.0.2:80>
    ServerName    sitio7.com
    DocumentRoot    /var/www/sites/sitio7
</VirtualHost>
<VirtualHost    10.0.0.2:80>
    ServerName    sitio8.com
    DocumentRoot    /var/www/sites/sitio8
</VirtualHost>

Algumas explicações para o exemplo acima:
Usar o endereço do servidor em vez do argumento coringa *, faz com que os hosts virtuais atendam somente ao endereço IP especificado.  No entanto, como pode ser observado, o argumento para <VirtualHost> ainda precisará bater com o argumento para o NameVirtualHost com o qual o host virtual está vinculado.

6. Exibindo o mesmo conteúdo em vários endereços
Deseja-se ter o mesmo conteúdo exibido em dois dos seus endereços.  Uma situação que ocorre quando uma máquina possui dois endereços: um referente a rede interna de uma organização e outro para a rede internet. Veja o exemplo abaixo:

NameVirtualHost    192.168.1.10:80
NameVirtualHost    172.20.30.40:80

<VirtualHost    192.168.1.10:80 172.20.30.40:80>
    ServerName    sitio9.com
    DocumentRoot    /var/www/sites/sitio9
    ServerAlias    www.sitio9.com
</VirtualHost>

7. Verificando o entendimento do servidor Apache da configuração dos hosts virtuais
É instrutivo executar o comando apachectl e observar a configuração dos hosts virtuais da forma como o Apache analisou os arquivos de configuração. Um exame cuidadoso dos endereços IP e nomes de servidor pode ajudar a descobrir erros de configuração. O comando abaixo exemplifica o uso deste comando:

# apachectl -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
_default_:8081         server1.meusitio.com.br (/etc/apache2/sites-enabled/000-apps.vhost:10)
*:9000                 is a NameVirtualHost
           default server server1.meusitio.com.br (/etc/apache2/sites-enabled/000-ispconfig.vhost:10)
           port 9000 namevhost server1.meusitio.com.br (/etc/apache2/sites-enabled/000-ispconfig.vhost:10)
*:80                   is a NameVirtualHost
           default server server1.meusitio.com.br (/etc/apache2/sites-enabled/000-default:1)
           port 80 namevhost server1.meusitio.com.br (/etc/apache2/sites-enabled/000-default:1)
           port 80 namevhost enota.meusitio.com (/etc/apache2/sites-enabled/100-enota.meusitio.com.vhost:7)
           port 80 namevhost iss.meusitio.com (/etc/apache2/sites-enabled/100-iss.maeusitio.com.vhost:7)
           port 80 namevhost meusitio.com.br (/etc/apache2/sites-enabled/100-meusitio.com.br.vhost:7)
           port 80 namevhost educar.meusitio.com (/etc/apache2/sites-enabled/900-educar.meusitio.com.vhost:7)
           port 80 namevhost meusitio.com (/etc/apache2/sites-enabled/900-meusitio.com.vhost:7)
Syntax OK

Referências:
1- Apache Virtual Host documentation
2- Configurar domínios virtuais do Apache em máquina Linux/Debian

Neste post vamos tratar de algumas complementariedades importantes para o perfeito funcionamento do servidor de mapas Geoserver no Linux/Debian. Seguiremos uma linha de roteiro de instalação do ambiente e do aplicativo, com enfoque na segurança. Este post complementa os demais posts que fizemos abordando o servidor Geoserver.

1. Instalar o Java

O primeiro passo para o colocar o Geoserver em funcionamento é a instalação da máquina virtual Java, que pode ser realizado através de apt-get. Existe um post neste blog que descreve a instalação do Java, e isto pode ser verificado aqui.

2. Instalar o Tomcat
A maneira mais fácil é utilizando o apt-get. Existe um post neste blog que descreve a sua instalação do Tomcat, e isto pode ser verificado aqui.

Chamamos a atenção aos seguintes espectos:

  • a instalação default do Tomcat é na porta 8080. Se desejar alterar, por exemplo para a porta 8085, deve-se alterar o arquivo /etc/tomcat6/server.xml
  • para uma maior segurança, alterar os usuários iniciais e perfis em /etc/tomcat6/tomcat-users.xml, conforme post referenciado acima.
  • para verificar o bom funcionamento do Tomcat acessando a URL http://server-IP:8085/manager/html , com user/passw: admin / admin

3. Instalar o Geoserver
Existe um post neste blog que descreve a instalação do Geoserver, e isto pode ser verificado aqui. É baixar o arquivo do sitio do próprio aplicativo e descompactá-lo na pasta apropriada de forma ao Tomcat poder servir.

Para verificar o bom funcionamento do ambiente Java, Tomcat e o Geoserver, acessar a URL http://server-IP:8085/manager/html   (ou porta 8080 se não houve modificação). O usuário/senha default para login após a instalação é admin/geoserver.

Chamamos a atenção aos seguintes aspectos:

  • no momento da instalação também é gerado um outro usuário chamado “root”. Que deve ser utilizado em caso de alguma emergência, quando o login pelo administrador não for possível. A senha para este usuário estará disponibilizada no arquivo /var/lib/tomcat6/webapps/geoserver/data/security/masterpw.info
  • se não for utilizar os serviços WCS e WFS, desabitá-los:
    Retirar serviços desnecessários: services -> WCS (desmarcar “Enable WCS”) e services -> WFS (desmarcar “Enable WFS”).
  • alterar as informações de contato através de: About & Status –> Contact Information
  • é importante fazer a alteração da senha default do usuário admin através do menu Security -> Users,Groups,Rules -> admin
  • remover arquivo users.properties.olg: rm /var/lib/tomcat6/webapps/geoserver/data/security/users.properties.old
  • remover arquivo masterpw.info em /var/lib/tomcat6/webapps/geoserver/data/security/masterpw.info , após tomar conhecimento da senha do usuário “root” contido neste arquivo.
  • limitar a lista de SRS do serviço WMS apenas aqueles de necessidade: services -> WMS -> Limited SRS list. Esta caixa, por exemplo, poderia ser preenchida por: 4326, 4674, 3857, 4269
  • Quanto aos logs: em produção, fixar o perfil de logs Settings –> Global –> LoggingProfile –> PRODUCTION_LOGGING.properties
    • relatório de logs que obtemos em About&Status –> GeoserverLogs é oriundo do arquivo /var/lib/tomcat6/webapps/geoserver/data/geoserver.log
    • profile de logs:  Settings –> Global –> LoggingProfile   são os arquivos depositados  em /var/lib/tomcat6/logs

4. Geoserver atrás de um proxy
Não é uma boa política expor na internet o Geoserver, mesmo que se esteja usando o Tomcat ou o Jetty. Uma opção mais segura é utilizar um servidor web mais estável, como o Apache. Uma boa solução é lançar mão de um proxy através do servidor Apache. Este servidor redirecionaria as requisições para o Tomcat, que estaria mais seguro numa rede protegida interna. É isto que vamos descrever nesta parte deste post.
4.1 Habilitar protocolo ajp na máquina do Geoserver
Editar o arquivo /var/lib/tomcat6/conf/server.xml e descomentar a linha:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

Com isto cria-se um conector na porta 8009 para o protocolo ajp.
Não esquecer de reiniciar o tomcat:
# /etc/init.d/tomcat6 restart

AJP: “Apache JServ Protocol” – trata-se de um protocolo binário que pode redirecionar requisições de entrada de um servidor web para um servidor de aplicação que fica por trás do servidor web. Implementadores da Web normalmente usam o AJP em uma implantação de balanceamento de carga, onde um ou mais servidores Web de front-end alimentam pedidos para um ou mais servidores de aplicação. Tanto o container Apache Tomcat servlet como o container Jetty servlet suportam o AJP.

4.2 Instalar o Apache na máquina front-end
Existe um post neste blog que descreve a instalação do Apache, e isto pode ser verificado aqui.

4.3 Instalar módulos proxy do Apache na máquina front-end
# a2enmod proxy proxy_ajp
# /etc/init.d/apache2 restart

Existe um post neste blog que descreve os procedimntos para instalação de módulos do Apache, e isto pode ser verificado aqui.

4.4 Configurar o funcionamento do proxy
Editar o arquivo /etc/apache2/apache2.conf e inserir as seguintes linhas:

# ProxyPass
ProxyPass /geoserver   ajp://192.168.1.101:8009/geoserver
<Location /geoserver>
Order deny,allow
Deny from all
Allow from all
</location>

ProxyPass /meumapa    ajp://192.168.1.101:8009/meumapa
<Location /meumapa>
Order deny,allow
Deny from all
Allow from all
</location>

Os dois comandos de redirecionamento acima fará com que:
– toda requisição para /geoserver será redirecionada para o host 192.168.1.101, na porta 8009, utilizando o protocolo ajp
– toda requisição para /meumapa será redirecionada para o host 192.168.1.101, na porta 8009, utilizando o protocolo ajp

Não esquecer de reiniciar o apache:
# /etc/init.d/apache2 restart

4.5 Fazer requisições normalmente
utilizando um navegador, acessar normalmente o servidor de front-end através das seguintes URL:
http://<IP-servidor_front-end>/geoserver
http://<IP-servidor_front-end>/meumapa
Observe que o servidor de front-end é acessado normalmente pela porta 80.

5. Mensagem Importante
Se este post fora útil para você, não deixe de comentar. Além de ser um estímulo importante, pode melhorar este trabalho. Com certeza é muito mais trabalhoso fazer uma boa documentação do que implementar.

Sucesso!

Referências:
1- Instalar Geoserver no Linux – Debian

1. Variáveis de ambiente do servidor web
$_SERVER é um array contendo informação como cabeçalhos, paths, e localizações do script. Trata-se de uma variável ‘superglobal’, ou global automática. Isto simplismente significa que ela está disponível aos scripts em todos os escopos.

<?php
$indicesServer = array('PHP_SELF',
     'argv',
     'argc',
     'GATEWAY_INTERFACE',
     'SERVER_ADDR',
     'SERVER_NAME',
     'SERVER_SOFTWARE',
     'SERVER_PROTOCOL',
     'REQUEST_METHOD',
     'REQUEST_TIME',
     'REQUEST_TIME_FLOAT',
     'QUERY_STRING',
     'DOCUMENT_ROOT',
     'HTTP_ACCEPT',
     'HTTP_ACCEPT_CHARSET',
     'HTTP_ACCEPT_ENCODING',
     'HTTP_ACCEPT_LANGUAGE',
     'HTTP_CONNECTION',
     'HTTP_HOST',
     'HTTP_REFERER',
     'HTTP_USER_AGENT',
     'HTTPS',
     'REMOTE_ADDR',
     'REMOTE_HOST',
     'REMOTE_PORT',
     'REMOTE_USER',
     'REDIRECT_REMOTE_USER',
     'SCRIPT_FILENAME',
     'SERVER_ADMIN',
     'SERVER_PORT',
     'SERVER_SIGNATURE',
     'PATH_TRANSLATED',
     'SCRIPT_NAME',
     'REQUEST_URI',
     'PHP_AUTH_DIGEST',
     'PHP_AUTH_USER',
     'PHP_AUTH_PW',
     'AUTH_TYPE',
     'PATH_INFO',
     'ORIG_PATH_INFO') ;

echo '<table cellpadding="2">' ;
foreach ($indicesServer as $arg) {
     if (isset($_SERVER[$arg])) {
          echo '<tr><td>'.$arg.'</td><td>' . $_SERVER[$arg] . '</td></tr>' ;
     }
     else {
          echo '<tr><td>'.$arg.'</td><td>-</td></tr>' ;
     }
}
echo '</table>' ;
?>

Referências:
1- Variáveis Superglobais: $_server

Os testes foram realizados em uma máquina alvo com:
Linux kernel 2.6.32
SO GNU Linux/Debian 6 (Squeeze)
Servidor de página Apache/2.2.16 (Debian)

Esta máquina servidora fora acessada de uma outra, a máquina do usuário, através de um navegador.

1. Preparar o ambiente para os testes
a) Instalações necessárias na máquina servidora
# apt-get install apache2 apache2-utils apache2-doc php5 libapache2-mod-suphp

b) Criar um usuário web1 e a pasta para realização dos testes na máquina servidora, definindo uma senha e as propriedades da pasta:
# useradd web1
# passwd web1    (será solicitado um password para o usuário web1)
# mkdir /var/www/client1
# chown web1:web1 /var/www/client1/

c) Na máquina do usuário, colocar na tabela de hosts (/etc/hosts) o resolvedor de nome da máquina servidora para facilitar os testes:
192.168.1.5    www.meusitio.com    meusitio.com

d) Preparar a máquina servidora para escutar a porta 8080 nestes testes  (apenas uma conveniência, não é uma exigência).
No arquivo /etc/apache2/ports.conf, trocar as diretivas de portas ficando do seguinte modo:

NameVirtualHost *:8080
Listen 8080
# /etc/init.d/apache2 restart

e) Resultados principais desta etapa de preparação:
– módulos PHP e suPHP do Apache instalados;
– usuário e pasta para execução dos testes criados.

2. Construir um site virtual para auxiliar nos testes
Criar o arquivo de configuração de host virtual /etc/apache2/sites-available/meusitio com o seguinte conteúdo:

<VirtualHost *:8080>
      ServerAdmin webmaster@localhost
      ServerName www.meusitio.com
      ServerAlias meusitio.com
      DocumentRoot /var/www/client1
      <Directory />
           Options FollowSymLinks
           AllowOverride None
      </Directory>
      <Directory /var/www/client1/>
           Options Indexes FollowSymLinks MultiViews
           AllowOverride None
           Order allow,deny
           allow from all
      </Directory>
      ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
      <Directory "/usr/lib/cgi-bin">
           AllowOverride None
           Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
           Order allow,deny
           Allow from all
      </Directory>
      ErrorLog ${APACHE_LOG_DIR}/error.log
      # Possible values include: debug, info, notice, warn, error, crit,
      # alert, emerg.
      LogLevel warn
      CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

O que é importante observar agora neste arquivo:
– existindo arquivos PHP na pasta /var/www/client1/ estes serão executados pelo módulo PHP do Apache, e não pelo módulo suPHP.

3. Teste-1: módulo Apache PHP utilizado
Condição: módulos PHP e suPHP habilitados, mas módulos rewrite e suexec desabilitados. Arquivo de host virtual do Apache conforme item 2 acima.
Crie o arquivo /var/www/client1/index.php  com o seguinte conteúdo:
<?php phpinfo();?>

Fixe as permissões da seguinte forma:
# chmod 777 /var/www/client1/index.php
# chmod 777 /var/www/client1/

Acesse a partir de um navegador da máquina do usuário a URL http://meusitio.com  para obter a página normalmente contendo informações de configuração do ambiente PHP instalado.
Conclusão: módulo Apache PHP sendo utilizado normalmente, e executando o script PHP solicitado.

4. Teste-2: módulo Apache PHP buscado pelo Apache e não encontrado
Condição: módulo suPHP habilitado, mas módulos PHP, rewrite e suexec desabilitados. Arquivo de host virtual do Apache conforme item 2 acima.
Desinstalar o módulo PHP.
# a2dismod php5
# /etc/init.d/apache2 restart

Novamente com o navegador da máquina do usuário acessar o sítio preparado. A resposta será a tradicional mensagem de erro interno:

Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.

Conclusão: módulo PHP5 não encontrado, encaminhando uma mensagem de erro interno.

5. Teste-3: módulo suPHP buscado pelo Apache, mas requisitos de segurança provocam erro de execução e script não é executado.
Condição: módulo suPHP habilitado, e módulos PHP, rewrite e suexec desabilitados. Nova configuração do host virtual do Apache.
Modifique  o arquivo de host virtual /etc/apache2/sites-available/meusitio de forma a possibitar a chamada do módulo suPHP pelo Apache:

<VirtualHost *:8080>
       ServerAdmin webmaster@localhost
       ServerName www.meusitio.com  
       ServerAlias meusitio.com
       DocumentRoot /var/www/client1
       <Directory />
            Options FollowSymLinks
            AllowOverride None
       </Directory>
       <Directory /var/www/client1/>
             Options Indexes FollowSymLinks MultiViews
             AllowOverride None
             Order allow,deny
             allow from all
             <IfModule mod_suphp.c>
                  <FilesMatch "\.ph(p3?|tml)$">
                  SetHandler application/x-httpd-suphp
                  suPHP_AddHandler application/x-httpd-suphp
                  </FilesMatch>
             </IfModule>
       </Directory>
       ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
       <Directory "/usr/lib/cgi-bin">
             AllowOverride None
             Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
             Order allow,deny
             Allow from all
       </Directory>
       ErrorLog ${APACHE_LOG_DIR}/error.log
       # Possible values include: debug, info, notice, warn, error, crit,
       # alert, emerg.
       LogLevel warn
       CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

É importante observar agora neste arquivo:
caso esteja o módulo suphp habilitado, o script PHP será executado no modo CGI, sob o “wrapper” suphp.

Conclusão: A resposta será a tradicional mensagem de erro interno, conforme teste anterior, mas por outro motivo:  por requisitos de segurança, o suPHP só executa o arquivo de script PHP se as permissões de sua pasta e do próprio arquivo não contrariarem certas regras de segurança definidas em seu arquivo de configuração localizado em /etc/suphp/suphp.conf:
; Security options
allow_file_group_writeable=
allow_file_others_writeable=
allow_directory_group_writeable=
allow_directory_others_writeable=

Se todas estas quatro diretivas de segurança contiverem a indicação “false”, então as permissões da pasta e do arquivo de script PHP  (index.php) não poderão ser superiores a 755 e 644 respectivamente.  Como estavam com 777, motivou o erro.

Pode-se fazer algumas combinações de valores (como as abaixo) e verificar que sempre a resposta na tela do navegador será de indicação de erro:
pasta    –    arquivo
777    –    644
757    –    644
755    –    664
752    –    700
e assim por diante.

Além do resultado mostrado na tela do navegador, estes poderão ser também observados através dos arquivos de log:
/var/log/apache2/access.log
/var/log/apache2/error.log
/var/log/suphp/suphp.log

No entanto, se as diretivas de segurança do arquivo de configuração do suPHP forem alteradas, estes valores limitantes de 755 e 644 se deslocarão (sofrerão alterações, portanto).

Vejamos com mais atenção o que significa aquelas diretivas de segurança do suPHP, considerado o octeto “rwx” das permissões de pastas e arquivos:

  • allow_directory_group_writeable: negar a gravação de arquivos ou outros diretórios ao grupo, significa r_x para o octeto da pasta referente ao grupo.
  • allow_directory_others_writeable: idem anterior, referente aos “outros” usuários.

Assim, a permissão máxima para a pasta é 755.
Para os arquivos, o suPHP não permite execução de scripts PHP apenas sua leitura e interpretação.  Assim já se tem rw_.

  • allow_file_group_writeable: negar escrita ao grupo, acumula a permissão r__ ao grupo.
  • allow_file_others_writeable: negar escrita aos outros, acumula a permissão r__ aos outros.

Assim, tem-se o máximo 644 par arquivos. Para os arquivos, 644 significa “owner” com permissão de leitura e gravação, grupo com permissão somente de leitura, outros com permissão somente de leitura.

6. Teste-4:  módulo suPHP ativado pelo Apache, mas requisitos de segurança geram novos erros de execução
Condição: módulo suPHP habilitado, mas módulos PHP, rewrite e suexec desabilitados. Arquivo de host virtual do Apache conforme item 5 acima.

Com o suPHP o proprietário da pasta tem que ser o proprietário do arquivo.  Se isto não acontecer, mesmo que tenhamos 755/644 de permissões, teremos um erro interno de servidor.  Para realização deste teste, modifique o proprietário da pasta e verifique o erro mostrado na tela do navegador:
# chown root:web1 /var/www/client1/

Depois disso, pode-se fazer outras combinações (trocando o proprietário do arquivo) e observar novos casos de erros.  Ou seja, com o suPHP o proprietário da pasta tem de ser obrigatoriamente o proprietário do arquivo.

7. Teste-5: módulo PHP ativado e executa normalmente o arquivo independentemente de permissões e de quem seja o proprietário.

Condição: módulo PHP habilitado, e módulos suPHP, rewrite e suexec desabilitados. Arquivo de host virtual do Apache conforme item 5 acima.
Desabilitar o módulo suPHP e habilitar de volta o módulo PHP conforme comandos abaixo:
# a2dismod suphp
# a2enmod php5
# /etc/init.d/apache2 restart

Observar que agora quem será chamado pelo Apache para interpretar o script PHP é o módulo PHP.  Faça algumas combinações entre o proprietário da pasta e do arquivo PHP, deixando-os diferentes entre si. Com o navegador acesse a URL que será executado o script index.php e veja que o mesmo é executado sem problemas independentemente dos proprietários desencontrados entre pasta/arquivo.

Agora altere as permissões da pasta e do arquivo para valores altos (portanto, de maior risco de segurança para o sistema), e veja que o script PHP é novamente sempre executado sem problemas.

Conclusão geral:  a execução de escripts através do módulo suPHP é muito mais segura, oferecendo menores risco para o sistema.

8. Aproveitando para comparar os ambientes PHP
Os contextos PHP são diferentes quando o script PHP é executado através de mod_php e mod_suphp. Isso se torna evidente desde o primeiro momento quando se percebe que os dois módulo utilizam php.ini diferentes:
módulo PHP: utiliza /etc/php5/apache2/php.ini
módulo suPHP: utiliza /etc/php5/cgi/php.ini

Veja o quadro comparativo (a partir do resultado da chamada da função PHP phpinfo()):

Geral
Server API Apache 2.0 Handler CGI/FastCGI
Configuration File (php.ini) Path /etc/php5/apache2 /etc/php5/cgi
Loaded Configuration File /etc/php5/apache2 /etc/php5/cgi
Scan this dir for additional .ini files /etc/php5/apache2/conf.d /etc/php5/cgi/conf.d
Apache Environment
DOCUMENT_ROOT /var/www/client1 /var/www/client1
SCRIPT_FILENAME /var/www/client1/index.php /var/www/client1/index.php
GATEWAY_INTERFACE CGI/1.1 CGI/1.1
SCRIPT_NAME /index.php /index.php
Environment
APACHE_RUN_DIR /var/run/apache2
APACHE_RUN_GROUP www-data
APACHE_RUN_USER www-data
APACHE_LOG_DIR /var/log/apache2
apache2handler
User/Group www-data(33)/33
Loaded Modules core mod_log_config mod_logio prefork http_core mod_so mod_alias mod_auth_basic mod_authn_file mod_authz_default mod_authz_groupfile mod_authz_host mod_authz_user mod_autoindex mod_cgi mod_deflate mod_dir mod_env mod_mime mod_negotiation mod_php5 mod_reqtimeout mod_setenvif mod_status
PHP Variables
_SERVER[“HTTP_ACCEPT”] text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
_SERVER[“HTTP_CONNECTION”] keep-alive keep-alive
_SERVER[“PATH”] /usr/local/bin:/usr/bin:/bin /bin
_SERVER[“SCRIPT_FILENAME”] /var/www/client1/index.php /var/www/client1/index.php
_SERVER[“GATEWAY_INTERFACE”] CGI/1.1 CGI/1.1
_SERVER[“SERVER_PROTOCOL”] HTTP/1.1 HTTP/1.1
cgi-fcgi
cgi.discard_path 0
fastcgi.logging 1
Core
PHP Version 5.3.3-7+squeeze14 5.3.3-7+squeeze14
include_path .:/usr/share/php:/usr/share/pear .:/usr/share/php:/usr/share/pear

9. Um FAQ rápido para ajudar a entender um pouquinho a mais

1- Quais os modos de funcionamento do Apache com o PHP aqui tratados neste post?
Fizemos testes com dois modos de funcionamento:
– utilizando o interpretador PHP como um módulo embutido (“built-in”) do Apache (mod_php);
– utilizando o interpretador PHP como um binário CGI, através da aplicação “wrapper” suphp (módulo suphp).

2- Que módulos próximos ao tema NÃO foram utilizados?
Não foram utilizados os seguintes módulos:
cgi
rewrite
suexec

Estes módulos ficaram desabilitados (a2dismod) ou até mesmo nem sequer carregados do repositório para a máquina.

3- Então posso carregar apenas o módulo PHP ou apenas o módulo suPHP e já poder executar scripts PHP?
Exatamente. Entretanto, executar scripts PHP através do módulo suPHP é mais seguro para o ambiente. No entanto, é mais lento e exigem alguns cuidados quanto a configurações por parte do usuário.

4- Então o que devo usar: PHP ou suPHP?
O suPHP diminui os riscos para o ambiente computacional. Vale a pena sempre buscar utilizar o suPHP para executar scripts PHP, apesar de um performance menor que o funcionamento com mod_php.

5- Como os módulos PHP e suPHP são referenciados no repositório Debian e facilmente localizados pelo Synaptic ?
Para o módulo PHP: procure o pacote php5. Marcando este pacote e fazendo sua instalação, o servidor de páginas Apache já pode responder a solicitações de páginas dinâmicas com scripts PHP simples. Não necessita de mais nada. Para instalar, carregue pacote “PHP”:
# apt-get install php5


Para o módulo suPHP: procure o pacote libapache2-mod-suphp. Marcando este pacote e fazendo sua instalação, o servidor de páginas Apache já pode responder a solicitações de páginas dinâmicas com scripts PHP simples. Não necessita de mais nada. Para instalar, carregue o pacote “libapache2-mod-suphp”:
# apt-get install libapache2-mod-suphp

6- Como habilitar e desabilitar os módulos necessários?
Simples, usando comandos como os exemplificados aqui:
# a2dismod cgi rewrite suexec
# a2enmod php5 suphp
# /etc/init.d/apache2 restart

7- Os módulos exigem configurações específicos depois de carregados?
Alguns sim, outros não. O módulo PHP não exige. Já o módulo suPHP tem seu módulo de configuração em /etc/suphp/suphp.conf.
No entanto é importante perceber que o ambiente PHP pode ser alterado através das variáveis do arquivo php.ini que é lido pelo interpretador PHP tanto no módulo PHP como no módulo suPHP.

8- Onde encontro os arquivos php.ini?
Se estiver utilizando o módulo PHP, o arquivo php.ini se encontra em /etc/php5/apache2/ . Se estiver utilizando o módulo suPHP, ele se encontra em /etc/php5/cgi/

9- Instalando o módulo PHP5 (“PHP5”), o que será carregado do repositório Debian?
Os seguintes pacotes (e alguns outros para resolver as dependências):

  • libapache2-mod-php5 (this package provides the PHP5 module for the Apache 2 webserver, as found in the apache2-mpm-prefork package).
  • php5-common (arquivos comuns para pacotes construídos a partir do código fonte do php5)

10- E instalando o pacote suPHP (“libapache2-mod-suphp”), o que será carregado do repositório Debian?
Três pacotes principais (e outras bibliotecas para resolver as dependências):

  • suphp-common (que gera em /etc/apache2/mods-available/ os arquivos suphp.conf e suphp.load)
  • apache2.2-common
  • php5-cgi (interpretador PHP CGI, construído para uso com Apache2. Será depositado em /usr/lib/cgi-bin/)

pois:
a) O pacote libapache2-mod-suphp depende dos pacotes suphp-common e apache2.2-common
b) O pacote suphp-common depende do pacote php5-cgi
Referências:
1- Módulos do Apache PHP, suPHP, suexec e rewrite no Linux – Debian
2- Documentação do Apache
3- suPHP Homepage

1. Comandos úteis
1.1 Para verificar disponibilidade de módulos Apache e seu estado
$ apache2 -l
// lista os módulos compilados com o servidor Apache. Estes módulos já estão no estado habilitado (ou seja, ativos e em funcionamento).
$ ls /usr/lib/apache2/modules/
// lista os módulos do Apache2 instalados (mas não necessariamente habilitados). Para um módulo ir ao estado habilitado, este necessita do comando a2enmod
$ ls -la /etc/apache2/mods-enabled/
// lista os módulos do Apache2 no estado habilitado. São links simbólicos para /etc/apache2/mods-available/
# a2enmod
// lista os módulos do Apache2 presentes na pasta default de arquivos de módulos: /usr/lib/apache2/modules/ (independentemente de estarem habilitados ou não).
// oferece a possibilidade de habilitar algum módulo.
# a2dismod
// Desabilita um módulo Apache2 (remove as entradas do diretório “/etc/apache2/mod-enabled/” relativo ao módulo).  Caso seja iniciado sem parâmetros, será mostrado a lista dos módulos habilitados e solicitado do usuário escolher um deles.

Exemplos:
i) Exemplo-1: verificar se os módulos suphp e suexec estão disponíveis no S.O.
$ ls /usr/lib/apache2/modules/ | grep -E  '(suphp|suexec)'
mod_suexec.so
mod_suphp.so

// Vê-se pela resposta do sistema que os módulos suphp e suexec estão disponíveis no ambiente do S.O.

ii) Exemplo-2: verificar se módulo suphp está no estado habilitado
$ ls -la /etc/apache2/mods-enabled | grep suphp
lrwxrwxrwx 1 root root 28 Set 8 18:14 suphp.conf -> ../mods-available/suphp.conf
lrwxrwxrwx 1 root root 28 Set 8 18:14 suphp.load -> ../mods-available/suphp.load

// Vê-se pela resposta do sistema que o módulo suphp já está no estado habilitado.

iii) Exemplo-3 verificar quais módulos foram compilados junto com o Apache
$ apache2 -l
Compiled in modules:
core.c
mod_log_config.c
mod_logio.c
prefork.c
http_core.c
mod_so.c

1.2 Para o PHP
$ php -v
// informa a versão do PHP, inclusive se o PHP é CLI ou CGI
$php -i
// Esta opção de linha de comando chama a função phpinfo() e imprime os resultados. Se o PHP não está funcionando bem, o “php -i” imprime mensagem de erro impressa antes ou dentro das tabelas de informação. Utilizando o modo CGI o resultado impresso está em HTML, e ela por isso é um pouco grande.
$ php -r 'print_r(get_defined_constants());' | less
// para verificar os valores das contanstes predefinidas do PHP
$ php -m
// lista os módulos PHP e os módulos Zend compilados e carregados
$ php -l
//Esta opção fornece uma maneira conveniente apenas realizar uma checagem de sintaxe no código PHP fornecido.

2. Configurações do Apache para usar o PHPÍcone do Apache
Existem três maneiras diferentes de se configurar o Apache para usar o PHP:

a) O interpretador PHP como um módulo embutido ("built-in") do Apache - mod_php;
b) O interpretador PHP como um binário CGI - mod_cgi.
c) O interpretador PHP como um binário CGI, porém usando uma aplicação "wrapper" - Suexec
     ou Suphp

No entanto, tem sido relativamente comum encontrarmos o interpretador PHP rodando em um único servidor sob mais de um modo simultâneo: uma versão rodando como módulo embutido do Apache e outra versão rodando como CGI.

2.1 PHP como módulo embutido Apache
Como módulo embutido do Apache (mod_php), o interpretador PHP é compilado para ser parte integrante do binário do Apache, fazendo com que o interpretador do PHP quando executado esteja no âmbito do processo Apache (com seu id/permissões). Cada processo filho do Apache já conterá uma imagem binária do interpretador PHP (já que este será parte do próprio Apache). Assim, o interpretador PHP é executado com as permissões do usuário do Apache (usualmente “nobody” no CenTOS ou “www-data” no Debian).

mod_php (ou o Apache2 Handler) é um módulo do Apache para executar scripts PHP, que possui a característica de manter os processos de trabalho em execução em vez de começar e parar PHP para cada requisição Apache (ou seja, característica de persistência). Ou de outra maneira, o mod_php conserva os processos PHP “vivos” e rodando em vez de repetidamente ter de criá-los e destruí-los (como é feito no modo CGI). Este comportamento traz  ganhos de performance, embora que também  traga algumas dificuldades quanto à permissões de arquivos considerando que os mesmos pertencem ao usuário “nobody” (no CenTOS) ou “www-data” (no Debian) – vide mais abaixo esse aspecto. Retomando, estando o interpretador PHP como um módulo embutido do Apache fará o servidor ter um melhor desempenho no tratamento de páginas dinâmicas contendo scripts PHP (assim como mais estável sob carga) quando comparado com o modo CGI.  Vale salientar que é no modo mod_php que a maioria dos sistemas pré-configurados dos hostings comerciais geralmente são entregues.

Estando o servidor configurado para rodar o interpretador PHP como um módulo embutido do Apache (mod_php), tem-se as opções de utilizar tanto o php.ini como .htaccess para alterar as configurações do Apache (em contraste com o modo CGI onde só terá a opção da utilização dos arquivos locais php.ini).

Como neste modo o interpretador PHP é executado com as permissões do usuário do Apache, existem restrições quanto ao acesso a arquivos e demais recursos, como as bases de dados. Por exemplo, se você estiver usando o PHP para acessar um banco de dados, a menos que o banco de dados tenha um controle de acesso interno, você terá que fazer o banco de dados acessível ao usuário “www-data”. Isso significa que um script malicioso pode acessar e modificar o banco de dados, mesmo sem um usuário e senha. É possível que um web “spider” passe em uma página web de administração do banco de dados e remova todos os bancos de dados. Você pode se proteger contra isso usando autorização do Apache, ou pode desenvolver seu modelo de acesso prório usando LDAP, arquivos .htaccess, etc. e incluir esse código como parte dos seus scripts PHP.

Um erro freqüente de segurança é dar ao Apache permissões de administrador (root), ou aumentar as habilidades do Apache de uma outra forma. Aumentar as permissões do usuário do Apache para administrador é extremamente perigoso e pode comprometer o sistema inteiro. Logo, sudo’ing, chroot’ing, ou então executar como root, não devem ser considerados por aqueles que não são profissionais em segurança.

Resumindo:
- interpretador PHP é parte integrante do Apache e roda obrigatoriamente com o id deste último
  ("nobody" no CenTOS ou "www-data" no Debian);
- não existe processo PHP externo;
- opções de usar tanto o php.ini como .htaccess para alterar as configurações do Apache;
- limitações para acesso a arquivos e base de dados;
- PHP persistente;
- PHP como um módulo do Apache apresenta melhor desempenho (assim como mais estável sob carga)
  comparado com o modo CGI (ou fastCGI e mod_suphp).

2.2 PHP como modo binário CGI
Modo CGI roda scripts PHP como módulo CGI, ao invés de módulo embutido Apache. O modo CGI também é reconhecido por sua flexibilidade em muitos aspectos. O CGI é executado como um processo independente para cada requisição, fazendo uma chamada exec() ou fork() para o executável do interpretador PHP (ou seja, o Apache faz a criação de um processo externo PHP para cada necessidade de execução de script PHP), o que significa que cada requisição ao Apache que necessite execução de script PHP haverá a criação de um novo processo para o interpretador PHP. Ou seja, o modo CGI não é persistente o que provoca uma certa perda de performance.

Em outras palavras, o modo CGI executa os scripts PHP em processos isolados do servidor Webserver. Ou seja, PHP funcionando no modo CGI é mais seguro do que funcionando como módulo Apache (mod_php) pois o servidor agora tem condições de gerenciar e controlar o acesso aos binários. Executar PHP como um CGI significa que você basicamente informa a seu sevidor web a localização do interpetador PHP (arquivo executável), e o servidor web dá inicio a execução daquele executável, dando a ele o script que voce chamou, isto toda vez que você visita a página. Isto significa que você carrega a página, o PHP necessita ler o arquivo php.ini e fazer sua configuração, necessita carregar todas suas extensões, e então necessita iniciar o trabalho de análise do script – existe muito trabalho repetido que no modo mod_php não existe.

O modo CGI é mais lento quando comparado com mod_php, devido justamente ao fato de que a cada nova solicitação ao Apache um novo processo do interpretador PHP é criado e posteriormente necessita ser destruído.

No modo CGI puro, os scripts não analisados e executados como usuário Apache (“nobody” no CenTOS ou “www-data” no Debian). Entretanto, se o CGI estiver usando uma aplicação “wrapper” (suexec ou suPHP – ver logo adiante neste post) os scripts serão executados com a identificação/permissões da conta do dono do script PHP (haverá um chaveamento na identificação do processo).

Quanto a possibilidade de alterar parâmetros de configuração do Apache, no modo CGI só haverá a opção de utilizar os arquivos locais php.ini (perdendo a possibilidade de se utilizar os arquivos .htaccess). Neste sentido, é importante perceber a diferença principal entre .htaccess ou php.ini:

  • o   .htaccess   pode ser colocado no diretório raiz e fazer efeito para todos os subdiretórios com apenas um arquivo;
  • o   php.ini  tem efeito apenas no diretório em que está colocado.
Resumindo:
- cada requisição do Apache criará um novo processo do interpretador PHP;
- PHP não persistente;
- os processos CGI do interpretador PHP herda o id/permissões do Apache;
- apenas o php.ini é utilizado para alterar as configurações do Apache (.htaccess NÃO utilizado)*;
- PHP como CGI é mais seguro que o PHP como módulo do Apache;
- o modo CGI é mais lento quando comparado com mod_php.

(*) mas pode ser colocado um arquivo .htaccess na pasta que este será lido. Para alterar as configurações do php.ini default, deve-se neste arquivo .htaccess ter o apontamento para o arquivo php.ini particular para o script em questão.

2.3 PHP como um binário CGI usando uma aplicação “wrapper” suexec ou suphp
O servidor Apache pode ser configurado como CGI usando uma aplicação “wrapper” para servir páginas dinâmicas de scripts PHP. Para isto deve ser instalando um dos dois módulos suexec ou suPHP (ou ambos):

  • Módulo suexec (mod_suexec);
  • Módulo suPHP (mod_suphp).

Estes wrappers são utilizados pelo Apache HTTP Server para chavear a identificação do processo CGI para outro usuário diferente do seu, antes de passar o controle para execução do programa CGI (para o interpretador PHP). De outra forma, suexec e suphp são módulos Apache (mod_suexec e mod_suphp) que permitem aos usuários do Apache executarem scripts CGI e SSI sob IDs dos proprietários destes scripts, chaveando do ID do servidor web (no Debian “www-data”, que recebe UID=33). Usado corretamente, esse recurso pode reduzir consideravelmente os riscos de segurança existentes permitindo aos usuários desenvolverem e executarem programas CGI ou SSI particulares sem riscos para o ambiente computacional.

Tanto o suexec como o suphp fazem várias verificações de segurança antes de decidir executar os scripts. Um pouco destas verificações:

  • verificar se o usuário que tem que executar o script é um usuário válido no sistema;
  • verificar se o arquivo não permite escrita pelo “world” (ou seja, no mínimo 755. Melhor seria 644);
  • requer que o diretório que contém o script CGI não permita escrita por outros (ou seja, 755);
  • verificar se o diretório é de propriedade do mesmo usuário;
  • verificar se o arquivo é de propriedade do mesmo usuário;
  • e mais algumas verificações adicionais…

Depois que todas estas verificações tenham sido concluídas com êxito, o wrapper chaveia o ID do processo: do UID do servidor web para o UID do usuário proprietário do script que será executado. Só então é que se inicia a execução do script PHP.

Caso as verificações tenham insucesso, ou caso ocorra falha quando da execução do script, o arquivo de log de erros do Apache indicará “Premature end of script headers”, e o arquivo de log de erros do wrapper indicará o problema com mais detalhes, por exemplo, “error: directory is writable by others”. Na tela do navegador do usuário, a indicação de erro será uma mensagem de “Internal Server Error” (error 500). Deve ser observado que o Debian Linux não faz automaticamente o “rotate” do arquivo de log do wrapper, o qual poderá crescer excessivamente. Para evitar isto, deve-se programar este ‘rotate’ através dos arquivos em /etc/logrotate.

Estes wrappers são muito importantes para os administradores de sites, pois caso um processo esteja consumindo exageramente o tempo de CPU, este terá seu proprietário rapidamente identificado. Caso o wrapper não estivesse sendo utilizado, não haveria condições de saber a quem pertencia o script problemático (pelo menos de forma rápida e direta), pois todos os processos PHP tanto no mod_php como CGI padrão pertencem a um mesmo proprietário (ao servidor web, que no caso do Debian possui id=”www-data”).

Sob execução de um wrapper, a manipulação dos arquivos PHP e as suas pastas não mais ocorrem como uid=”nobody” ( ou uid=”www-data”, para o caso do Debian), mas identificado como o usuário proprietário do script (e tendo suas permissões e propriedades). Com o wrapper torna-se possível o funcionamento do CMS sem a necessidade de fixar as permissões como 777 para as pastas e para os scripts PHP que serão executados, o que torna o site do usuário flexível no uso e seguro.

Resumindo:
- cada requisição do Apache criará um novo processo do interpretador PHP;
- PHP não persistente;
- o interpretador PHP passará por um chaveamento para estar associado ao id e permissões do
  proprietário do script PHP a ser executado;
- apenas o php.ini utilizado para alterar as configurações do Apache (.htaccess NÃO utilizado);
- PHP usando aplicação "wrapper:  é mais seguro que o PHP como módulo do Apache, bem
  como do modo CGI tradicional;
- os mecanismos suexec e suPHP do Apache proporcionam maior segurança para casos de ataques;
- alto custo de performance, sendo mais lento que o mod_php e modo CGI puro.

a) Suexec
Suexec – “Switch” o usuário antes de executar programas externos. O Suexec consiste de um módulo para o web server e um binário executável os quais agem como um wrapper. Suexec exige uma configuração individual para cada host virtual.

Antes de executar o script, Suexec faz o log da execução em suexec.log (se não mudou durante a compilação). O ponto negativo do suexec é que ele é o mais lento de todos: mais lento que mod_php, CGI padrão e suphp.

b) SuphpLogo do módulo do suphp
Suphp é um módulo Apache (mod_suphp) e executa scripts php como CGI. Seu funcionamento é muito semelhante ao Suexec. Suphp não exige configuração para cada host virtual. Ele simplesmente executa os scripts php com as permissões do usuário proprietário do script. Suphp é mais lento que o módulo CGI padrão e muito mais lento que o módulo embutido PHP do Apache – modphp (cerca de 25 vezes). Entretanto ele é mais rápido que o suexec. Suphp inicia um processo PHP a cada solicitação do Apache. Isto implica que ele não utiliza nenhum recurso (memória RAM, processador, …) quando nenhuma página está sendo solicitada. Podemos considerar que o Suphp é ideal para websites de tráfego não elevado.

Existem desvantagens em usar o Suphp ?
O Suphp tem um defeito que é causar uma perda de performance no servidor comparado com o módulo embutido PHP (modphp). Suphp executa scripts PHP em modo CGI, o qual, como temos comentado neste post, causa uma certa lentidão.

c) Comando associado para instalação:
# apt-get install apache2-suexec libapache2-mod-suphp
Suexec e Suphp possuem similaridades por se tratar de uma mesma implementação, porém de abrangência diferenciada. O Suexec é utilizado para qualquer aplicação externa que utilize CGI ou SSI (como Perl e PHP, por exemplo) enquanto o Suphp é específico para o PHP e traz melhores resultados de desempenho. Ambos, Suexec e Suphp, podem ser utilizados simultaneamente em uma mesma máquina sem quaisquer problemas.


2.4 Como verificar sob qual modo o PHP está sendo executado? Como obter mais informações do ambiente Apache sendo executado?

Existem várias maneiras.
a) executar um pequeno programa PHP do tipo <?php phpinfo() ?>
Observar a resposta quanto a diretiva “Server API”, que basicamente poderá vir como “CGI/FastCGI” ou “Apache 2.0 Handler”, dependendo do modo como o Apache está utilizando o interpretador PHP.

b) Executar o programa PHP abaixo:
<?php
echo "Hostname: ". @php_uname(n) ."<br \>";
if (function_exists( 'shell_exec' )) {
echo "Hostname: ". @gethostbyname(trim(`hostname`)) . "<br \>";
} else {
echo "Server IP: ". $_SERVER['SERVER_ADDR'] . "<br \>";
}
echo "Platform: ". @php_uname(s) ." ". @php_uname(r) ." ". @php_uname(v) ."<br \>";
echo "Architecture: ". @php_uname(m) ."<br \>";
echo "Current script owner:: ". get_current_user () ." ( UiD: ". getmyuid() .", GiD: ". getmygid() ." )<br \>";
echo "ID do processo PHP: ". getmypid()."<br \>";
echo "Curent Path: ". getcwd () ."<br \>";
echo "Server Type: ". $_SERVER['SERVER_SOFTWARE'] . "<br \>";
echo "Server Admin: ". $_SERVER['SERVER_ADMIN'] . "<br \>";
echo "Server Signature: ". $_SERVER['SERVER_SIGNATURE'] ."<br \>";
echo "Server Protocol: ". $_SERVER['SERVER_PROTOCOL'] ."<br \>";
echo "Server Mode: ". $_SERVER['GATEWAY_INTERFACE'] ."<br \>";
?>

Uma possível resposta seria:
Hostname: server1.meusite.com.br
Hostname: 66.92.73.198
Platform: Linux 2.6.32-042stab059.7 #1 SMP Tue Jul 24 19:12:01 MSK 2012
Architecture: i686
Current script owner:: web1 ( UiD: 5004, GiD: 5005 )
ID do processo PHP: 29504
Curent Path: /var/www/clients/client1/web1/web/subdominios/meuscript
Server Type: Apache/2.2.16 (Debian)
Server Admin: webmaster@meusite.com.br
Server Signature:
Apache/2.2.16 (Debian) Server at equipe.meusite.com.br Port 80
Server Protocol: HTTP/1.1
Server Mode: CGI/1.1

3. Alguns apontamentos importantes

3.1) Instalações padrões
a) Servidor LAMP padrão
#apt-get install apache2 apache2-utils libapache2-mod-php5 php5 mysql-server-5.0 php5-mysql
// Vê-se uma instalação simples, configurando o Apache para executar o interpretador PHP como seu módulo embutido (“built-in”) – modphp;
obs: vide post Instalar servidor LAMP (Linux + Apache + PHP + MySQL) no Debian

b) Servidor típico preparado para suportar o WordPress
Instalar servidor LAMP, na forma apontada acima
# apt-get install libapache2-mod-suphp
# a2enmod rewrite
# a2dismod php5
# a2enmod suphp
obs: vide post Instalar o WordPress no Linux distribuição Debian

3.2) Quanto ao CORE do Apache:
# apt-get install apache2 apache2.2-common apache2-doc apache2-mpm-prefork apache2-utils
i) apache2-mpm-prefork:
é o padrão Linux Apache MPM (Multi-Processing Modules). Neste modo, um único servidor de processos master gera vários servidores de processos filhos (ou sobressalentes) para tratar as solicitações de entrada. O servidor master bifurca (gera) processos servidores filhos antes deles serem utilizados. É uma implementação non-threaded. Cada processo manipula apenas uma conecção de cada vez. Não é tão rápida quanto ao modo threaded (apache2-mpm-worker), porém é avaliada como a mais estável. Para servidores web de alto tráfego é recomendado o modo apache2-mpm-worker.

OBS: para saber qual o modo do servidor Apache instalado, basta usar o comando:
# dpkg -l | grep apache

ii) apache2:
metapacote do servidor HTTP Apache.
iii) apache2-common:
instala importantes arquivos de suporte ao Apache2.0 requerido para todas as plataformas.
apache2-utils:
provê alguns programas adicionais úteis para qualquer webserver. Isto inclui:
– ab (Ferramenta de avaliação de desempenho – “benchmark” – do Apache);
– logresolve (resolve endereços IP para nomes de máquina nos arquivos de log);
– htpasswd (Manipulate basic authentication files)
– htdigest (manipula arquivos de autenticação “basic”);
– dbmmanage (Manipula arquivos de authenticação básicas no formato DBM, usando perl)
– htdbm (Manipula arquivos de authenticação básicas no formato DBM, usando APR)
– rotatelogs (periodicamente para de escrever em um arquivo de log e abre um novo)
– split-logfile (Divide um único log que inclui múltiplos vhosts)
– checkgid (Verifica se o chamador pode setgid para um grupo especificado )
– check_forensic (Extrai a saída mod_log_forensic dos arquivos de log do Apache)
– httxt2dbm (Gera arquivos dbm para uso com RewriteMap)

3.3) Quanto aos MÓDULOS do Apache:
apt-get install libapache2-mod-php5 libapache2-mod-suphp libapache2-mod-fcgid apache2-suexec
i) libapache2-mod-php5:
módulo PHP para o webserver Apache2 (este módulo funciona apenas com o modo Apache prefork MPM, pois ele não é compilado com “thread-safe”). As seguintes extensões estão embutidas (“built in”):
bcmath bz2 calendar Core ctype date dba dom ereg exif fileinfo filter ftp gettext hash iconv json libxml mbstring mhash openssl pcre Phar posix Reflection session shmop SimpleXML soap sockets SPL standard sysvmsg sysvsem sysvshm tokenizer wddx xml xmlreader xmlwriter zip zlib.

ii) libapache2-mod-fcgid:
módulo de alta performance alternativo ao mod_cgi ou mod_cgid. Instancia um número suficiente do programa CGI para tratar solicitações concorrentes. Estes programas permanecem em execução para tratarem futuras solicitações entrantes. Tem sido a preferência dos desenvolvedores PHP como alternativa para executarem processos em mod_php, apresentando uma performance muito similar.

iii) apache2-suexec:
programa suexec padrão para o mod_suexec do Apache 2. Fornece o programa auxiliar suexec padrão para o mod_suexec. Esta versão é compilada com /var/www como a raiz dos documentos (“document root”) e public_html como sufixo para diretórios de usuário (“userdir”). Se houver necessidade de configurações diferentes, deve-se usar o pacote apache2-suexec-custom.

iv) libapache2-mod-suphp:
módulo suPHP do Apache2 para executar o interpretador PHP com as permissões do proprietário do script. Se há a necessidade de se executar um webserver para muitos usuários diferentes, é recomendável que cada script PHP seja executado com a identidade do usuário proprietário daquele script – em vez de ter todos os scripts sendo executados através do mesmo usuário (tipicamente www-data nos sistemas Debian). suphp permite isto facilmente, alterando o uid do processo de execução do interpretador PHP para o do proprietário do script php .
O suPHP consiste de dois componentes: mod_suphp e suPHP.

  • mod_suphp: módulo do Apache2, que substitui mod_php (podendo os dois módulos conviverem simultaneamente).
  • suPHP: binário “setuid root” que substitui Apache suEXEC. É chamado pelo módulo do Apache para mudar a identificação do usuário (“uid” – user id) do processo de execução do interpretador PHP. Normalmente, o Apache roda com uid=”nobody” (no CenTOS) ou uid=”www-data” (no Debian).

Com o uso do binário “suphp setuid root” (do pacote suphp-common), este módulo do Apache2 altera o uid do processo que está com o interpretador PHP para o proprietário do script PHP. É uma alternativa compatível módulo mod_fastcgi do Apache2.
Notas:

  • Ao instalar libapache2-mod-suphp, automaticamente também está sendo instalado o pacote suphp-common.
  • O arquivo de configuração do suPHP está em /etc/suphp/suphp.conf
  • O arquivo de configuração para o módulo suPHP  está em /etc/apache2/mods-enabled/suphp.load
  • O arquivo de configuration do suPHP para o Apache está em  /etc/apache2/mods-enabled/suphp.conf
  • O arquivo de log do suPHP está em /var/log/suphp/suphp.log.
  • O suPHP necessita do php5-cgi para ser instalado. Ele usa PHP CGI para iniciar a execução dos scripts.Por esta razão, suphp é muito mais lento que mod_php. Porém Suphp adiciona segurança e identificação aos usuários que executam os scripts PHP.

v) mod_rewrite:
é um módulo do servidor Apache2, responsável pela reescrita de URLs em páginas Web. Ao instalar o Apache2, este módulo estará disponível em /usr/lib/apache2/modules/mod_rewrite.so , embora ainda não ativado. Seu principal objetivo é tornar as URL’s mais “amigas” dos usuários e dos motores de busca. Na verdade, o módulo mod_rewrite permite ao usuário fazer quase qualquer coisa nas solicitações entrantes ao servidor Apache2. Para funcionar, o mod_rewrite necessita ser ativado e da existência de um arquivo .htaccess devidamente configurado (veja detalhes em Configuração .htaccess do Apache2). Para ativar o mod_rewrite no Debian basta um comando simples: “a2enmod rewrite”.
Este módulo é especialmente importante quando se utiliza CMSs, como WordPress ou outros. Observe que os search engines — como o Google — não têm acesso aos arquivos dinâmicos dos sites. Os “spiders” acessam apenas o código (X)HTML gerado por eles. Um “spider” é como um usuário qualquer, embora seja uma ferramenta automatizada que percorre os links que encontra e cria um índice que será usado pelo sistema de busca.
Sendo assim, uma página que antes seria acessada pela URL:
http://www.seusite.com/index.php?data=01-02-2005&nome=meu-artigo
agora será acessada por:
http://www.seusite.com/01/02/2005/meu-artigo

A URL antiga continuará funcionando e o buscador só passará a listar a nova URL se todos os links para a referida página forem atualizados para a nova URL. A troca — ou reescrita — das URLs é feita pelo apache de maneira transparente ao usuário, portanto, apenas o servidor tem conhecimento desta reescrita. O usuário, assim como o “spider”, não consegue perceber este processo. A reescrita (feita pelo mod_rewrite) é um processo interno ao servidor web. Este analisa uma regra de reescrita (RewriteRule) existente em um arquivo .htaccess, executa um redirecionamento e entrega o recurso ao user agent sem informar uma nova URL.

3.4) Especialmente, quanto ao funcionamento do PHP
apt-get install php5 php5-common php5-cli php5-cgi
i) php5:
metapacote que dá garantias de se ter instalado pelo menos uma das quatro versões do interpretador PHP5. Removendo este pacote não removerá o PHP do sistema, no entanto pode remover outros pacotes que dependam deste.
ii) php5-common:
contém a documentação e arquivos exemplos relevantes para todos os outros pacotes construídos do fonte php5.
iii) php5-cli:
interpretador de linha de comando para linguagem de script php5 encontrado em /usr/bin/php5. Muito útil para testar scripts PHP a partir de um shell ou executar arquivos batch de shell scripting. Observe que o PHP está disponível no Debian como CLI ou CGI, pelos pacotes php5-cli e php5-cgi.
iv) php5-cgi:
interpretador de scripts PHP no modo CGI encontrado em /usr/lib/cgi-bin/php5. O Suphp necessita do php5-cgi para ser instalado.  Foi construído para uso no Apache2 com “mod_actions”, ou com qualquer outro CGI httpd que suporte mecanismos similares.
Nota: a maioria dos usuários do Apache provavelmente utilizam o pacote libapache2-mod-php5. Observe que o PHP está disponível no Debian como CLI ou CGI, pelos pacotes php5-cli e php5-cgi.

3. Executando através dos módulos SuEXEC e SuPHP

a) 500 Internal Server Error

Isto significa que suphp está provavelmente funcionando, porém por alguma razão ele não permitiu a execução do script.
Possiveis razões para isto:

    •   Verifique se você não tem qualquer opcode PHP  caching (APC, etc) sendo executado.  Se você está executando qualquer tipo de cache   PHP cache, suphp nunca funcionará. Você deve desabilitar seu cache de opcode.  Se você está usando APC, você pode desabilitar seu  system-wide by simplesmente editando /etc/php5/conf.d/apc.ini  e comentar a linha abaixo com ponto e vírgula como abaixo:

;extension=apc.so

    • Um outro elemento importante são as permissões dos arquivos. SuPHP falhará (com um 500 Internal Server Error) se qualquer arquivo que tenha permissões que não sejam permitidas, conforme definido em /etc/suphp/ suphp.conf. Por exemplo:

; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false

  • As permissões do arquivo/pasta são excessivamente permissivas. Arquivos devem ter permissões  644 ou menores e pastas 755 ou menores, caso contrário suPHP  recusará analisar o script.
  • O arquivo é de propriedade do usuário apache. Se a questão principal para usar suPHP é separar usuário apache do usuário proprietário do script, a criação de arquivos com propriedade de www-data é um passo para trás.  Por padrão, o proprietário do script deve ter um uid superior a 100 pora o suPHP aceitar. Isto significa que os arquivos com propriedade pertencente a www-data não funcionará. Você poderá precisar de ajustar min_gid em /etc/suphp.conf  de 100 para 33. Obviamente, isso não deve ser um problema se você só tem hosts virtuais.
  • Tabém deve ser verificado se o arquivo /var/log/suphp/suphp.log   não ultrapassou 2GB.
  • Por último, verifique /var/log/suphp/suphp.log e  /var/log/apache2/error.log por sugestões.

b) Arquivo de configuração do suPHP
Como dito, o arquivo de configuração está em /etc/suphp/suphp.conf, cujas instruções deconfiguração podem ser encontradas no site oficial do suPHP.
Aqui vamos tecer alguns detalhes:
docroot=/var/www:${HOME}/public_html ; o formato padrão
docroot=/* ; o motor suPHP irá analisar em qualquer lugar do sistema de arquivos, e não apenas no diretório html padrão.
check_vhost_docroot ; Verifica se o script PHP está dentro do DOCUMENT_ROOT especificado pelo webserver. Esta opção destina-se a evitar links simbólicos para além do diretório página. Você pode querer desativá-lo, quando você estiver usando mod_vhost_alias ou a diretiva Alias. Esta opção é desabilitada por padrão, se em tempo de compilação a opção “- disable-check-docroot” for especificada, caso contrário, é ativada por padrão.

4. Outros aspectos relevantes sobre o PHPÍcone do PHP
A partir versão 4.3.0, o PHP suporta um novo tipo SAPI (“Server Application Programming Interface”) chamado CLI que significa Command Line Interface. Como o próprio nome indica, essa SAPI tem foco no desenvolvimento de aplicações shell (ou no terminal/linha de comando) com o PHP. Há algumas diferenças entre a a CLI SAPI e a CGI SAPI. Mas é errado dizer que a versão CLI e CGI são SAPIs diferentes pelo motivo que elas compartilham muitos comportamentos idênticos.

Por “default”, o PHP é construído como dois programas: CLI e CGI. A versão CGI possibilita aos usuários executarem diferentes scripts PHP sob diferentes user-ids. De muitas maneiras, o SAPI CLI funciona da mesma forma como o SAPI CGI e outras SAPIs. No entanto, é importante ter o conhecimento de onde eles diferem porque pode afetar diretamente como se escreve os scripts. Podemos resumir da seguinte forma:

  • PHP CLI é a interface de linha de comando para o PHP (isto é, para criação de aplicações standalone);
  • PHP CGI é a “common gateway interface” para o PHP (isto é, voltada para aplicações web). Entre outras coisas ela manipula cabeçalhos HTTP e certos parâmetros de segurança.

Ou com mais detalhes, estas são as diferenças mais importantes entre CLI e CGI:

  • Ao contrário da SAPI CGI, por padrão CLI não escreve cabeçalhos para a saída;
  • Há algumas diretivas do php.ini que são sobrescritas pela SAPI CLI porque não fazem sentido no ambiente shell:
    • html_errors: o padrão CLI é FALSO
    • implicit_flush: o padrão CLI é TRUE
    • max_execution_time: o padrão CLI é 0 (ilimitado)
    • register_argc_argv: o padrão CLI é TRUE
  • O usuário pode ter argumentos na linha de comando para o script! A variável “$ argc” informa o número de argumentos passados ​​para a aplicação. E o array “$ argv” informa os argumentos.
  • Existem três novas constantes definidas para o ambiente shell: STDIN, STDOUT, STDERR. Todos elas são manipuladores de arquivos para dispositivos shell correspondentes. Por exemplo STDIN é o manipulador para fopen(‘php://stdin’, ‘r’). Assim, você pode ler uma linha de stdin como esta: $strLine = trim(fgets(STDIN));. STDIN já está definido para você pelo PHP CLI!
  • PHP CLI não altera o diretório atual para o diretório de execução do script. O diretório atual para o script será o diretório onde se digitou o comando PHP CLI.
  • Há um número de opções úteis disponíveis para PHP CLI. Que lhe permitirá obter algumas informações valiosas sobre a configuração do php, sob o script php ou ainda executá-lo em diferentes modos.

Links:
1- Instalar servidor LAMP (Linux + Apache + PHP + MySQL) no Debian
2- Configurar domínios virtuais do Apache em máquina Linux/Debian
3- Configuração .htaccess do Apache2
4- Documentação do Apache: suEXEC Support
5- PHP CLI vs. PHP CGI
6- Utilizando o PHP na linha de comando
7- MDLog:/sysadmin
8- Exercícios para compreender o funcionamento dos módulos PHP e suPHP