Programação Por Equipe DevBras

Capa do artigo: Erro 403 no Apache: o servidor achou a pasta e recusou a porta

Erro 403 no Apache: o servidor achou a pasta e recusou a porta

Leia o log de erro para separar as três causas do 403 no Apache, permissão no disco, pasta sem index e regra de acesso, e corrija cada uma sem abrir permissão demais.

A URL está certa, o arquivo existe e o Apache responde "403 Forbidden". Reiniciar de novo não muda nada, porque o servidor entendeu o pedido e decidiu não entregar. A resposta curta: abra o log de erro do Apache, não a página genérica. A linha correspondente diz qual das três causas é a sua: o usuário do Apache não consegue ler o arquivo ou atravessar uma pasta do caminho, o endereço aponta para um diretório sem arquivo index e a listagem está desligada, ou uma regra de acesso na configuração nega aquele caminho ou aquele cliente.

Cada causa tem uma frase própria no log e um conserto próprio. Nenhum deles é chmod 777.

Por que o Apache responde 403

404 é "não achei". 403 é "achei e não vou entregar". Para chegar no 403, o Apache já resolveu o endereço para um caminho no disco ou para uma regra da configuração. A recusa acontece depois, em uma de três barreiras.

A barreira do sistema de arquivos

O processo do Apache roda com um usuário sem privilégios, www-data no Debian e no Ubuntu, apache no RHEL e derivados. Para ler /var/www/loja/public/index.html, esse usuário precisa de permissão de leitura no arquivo e de permissão de execução, que em diretório significa "atravessar", em cada pasta do caminho: /var, /var/www, /var/www/loja e /var/www/loja/public. Uma única pasta fechada no meio já basta. O caso clássico é o projeto dentro de /home/usuario, que em várias distribuições vem com permissão 750 ou 700.

Em sistemas com SELinux ativo, como RHEL, Rocky e Fedora, existe uma quarta camada: mesmo com as permissões certas, o arquivo precisa ter o rótulo que o Apache pode ler. Arquivo copiado de outro lugar costuma vir com o rótulo errado.

A barreira do diretório sem index

Quando a URL aponta para uma pasta, o Apache procura os arquivos listados em DirectoryIndex, normalmente index.html e, com PHP configurado, index.php. Se nenhum existe e Options -Indexes está em vigor, não há o que mostrar, e a resposta é 403. Isso é proteção, não defeito: listar o conteúdo da pasta para qualquer visitante expõe arquivo que ninguém deveria ver.

A barreira das regras de acesso

No Apache 2.4, quem decide é a diretiva Require, em blocos como <Directory> e <Location> ou em arquivos .htaccess. A configuração padrão do Debian nega acesso à raiz do disco e libera /var/www. Um site com DocumentRoot em outra pasta, como /srv/loja, herda a negação até ganhar um Require all granted próprio. No WampServer e em ambientes locais parecidos, a regra costuma ser Require local: funciona no próprio computador e dá 403 para quem acessa pela rede.

Como diagnosticar e corrigir o 403

  1. Reproduza o erro e leia a linha correspondente no log de erro do site.
  2. Identifique a causa pela frase do log.
  3. Corrija só a barreira apontada, com o mínimo de permissão necessário.
  4. Confira a sintaxe, recarregue e teste de novo com curl.
# Debian e Ubuntu
sudo tail -f /var/log/apache2/error.log

# RHEL, Rocky, Alma
sudo tail -f /var/log/httpd/error_log

# em outro terminal
curl -I http://loja.exemplo.com.br/

Se o site tem ErrorLog próprio no VirtualHost, olhe esse arquivo. As frases mudam um pouco entre versões, mas o padrão é este:

  • "Permission denied" ou "search permissions are missing on a component of the path": barreira do sistema de arquivos.
  • "No matching DirectoryIndex" e "forbidden by Options directive": diretório sem index com listagem desligada.
  • "client denied by server configuration": regra de acesso.

Corrigindo permissão no disco

O namei mostra a permissão de cada componente do caminho, e o teste com sudo -u confirma o que o Apache enxerga:

namei -l /var/www/loja/public/index.html
sudo -u www-data test -r /var/www/loja/public/index.html && echo legivel

# dono: o usuário de deploy; grupo: o do Apache
sudo chown -R deploy:www-data /var/www/loja
sudo find /var/www/loja -type d -exec chmod 755 {} +
sudo find /var/www/loja -type f -exec chmod 644 {} +

Pastas com 755 e arquivos com 644 deixam o Apache ler sem permitir que ele escreva. Se a aplicação precisa gravar uploads ou cache, dê escrita ao grupo só nessa pasta específica. Com SELinux, confira o rótulo com ls -Z e restaure o padrão com sudo restorecon -Rv /var/www/loja. Desligar o SELinux para fazer o 403 sumir troca um erro visível por um risco invisível.

Corrigindo index e regra de acesso

Para a pasta sem index, coloque o arquivo index que a aplicação espera, ou confira se o PHP está configurado para que index.php seja reconhecido. Não ligue Options +Indexes só para o erro sumir. Para a regra de acesso, procure o bloco que cobre o caminho:

<Directory /srv/loja/public>
    Options -Indexes
    AllowOverride None
    Require all granted
</Directory>

Se a configuração ainda tem Order allow,deny e Allow from all, é sintaxe do Apache 2.2. Ela só funciona com o módulo de compatibilidade e, misturada com Require, gera resultados difíceis de prever. Migre tudo para Require. Depois de mexer, rode sudo apache2ctl configtest e sudo systemctl reload apache2. A configuração dos blocos por site está detalhada em vários sites no mesmo Apache.

Erros comuns

  • Aplicar chmod -R 777. O 403 some e qualquer processo da máquina passa a poder alterar o seu site, inclusive um script invadido.
  • Olhar só a página do navegador. Ela é igual para as três causas. Sem o log, você troca configuração no escuro.
  • Corrigir o arquivo e esquecer a pasta do meio. O index.html tem 644, mas /home/usuario tem 700, e o Apache continua sem atravessar.
  • Ligar a listagem de diretório para resolver. O erro some e a pasta passa a exibir backups e arquivos de configuração.
  • Desligar o SELinux. Resolve o sintoma, remove uma proteção do servidor inteiro e o próximo arquivo copiado volta a dar problema quando alguém religar.
  • Editar o .htaccess com AllowOverride None ativo. O arquivo é ignorado, e você testa regras que o Apache nem lê.

Checklist

  • A linha do log de erro correspondente ao pedido foi encontrada.
  • namei -l mostra permissão de travessia em todas as pastas do caminho.
  • O teste com sudo -u www-data, ou o usuário do Apache na sua distribuição, consegue ler o arquivo.
  • Pastas estão com 755 e arquivos com 644, e escrita só onde a aplicação precisa.
  • Existe um arquivo index na pasta pública, e a listagem continua desligada.
  • O bloco <Directory> do site tem Require all granted e nada da sintaxe 2.2.
  • Com SELinux, o rótulo dos arquivos foi restaurado com restorecon.

Abra o log de erro do seu Apache e procure a última linha com "denied". Ela fala de permissão no disco ou de uma regra que você mesmo escreveu e esqueceu?

Avalie este artigo

Referência: http://forum.wampserver.com/read.php?2,151925