kb.erickguedes.com
Apache HTTP Server: Configuração e Administração

Hardening e Produção

Aula 5 de 5

Hardening do Apache

Ocultando Informações do Servidor

# /etc/apache2/conf-available/security.conf ou httpd.conf
ServerTokens Prod         # Apenas "Apache" no header
ServerSignature Off       # Remove assinatura em páginas de erro

# Antes: Apache/2.4.62 (Ubuntu) Server at site.com Port 80
# Depois: Apache
# Aplicar configuração
sudo a2enconf security
sudo systemctl reload apache2

# Verificar resultado
curl -I http://localhost | grep Server

Removendo Módulos Desnecessários

# Módulos comuns que devem ser removidos em produção
sudo a2dismod autoindex    # Listagem de diretórios
sudo a2dismod info         # Informações do servidor
sudo a2dismod status       # Status do servidor (se não usado)
sudo a2dismod userdir      # Diretórios de usuário (~user)

# Listar módulos ativos após remoção
sudo apache2ctl -M

Diretivas de Segurança Essenciais

# Proteger arquivos ocultos
<DirectoryMatch "^/\..*">
    Require all denied
</DirectoryMatch>

# Desabilitar trace (evita XST)
TraceEnable Off

# Limitar métodos HTTP
<LimitExcept GET POST HEAD>
    Require all denied
</LimitExcept>

# Cookie seguro
Header always edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=Lax

mod_security (WAF)

# Instalar mod_security
sudo apt install libapache2-mod-security2 -y
sudo a2enmod security2

# Copiar configuração padrão
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
# /etc/modsecurity/modsecurity.conf
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml
SecRequestBodyLimit 13107200
SecRequestBodyInMemoryLimit 13107200

# Regras básicas
SecRule ARGS "@contains select" "id:1000,deny,status:403,msg:'SQL Injection attempt'"
SecRule ARGS "@contains <script" "id:1001,deny,status:403,msg:'XSS attempt'"

# Paranoia level (1-4)
SecAction "id:900000,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=2"
# Usar OWASP CRS (Core Rule Set)
sudo apt install modsecurity-crs -y
sudo cp -r /usr/share/modsecurity-crs/rules/ /etc/modsecurity/
sudo systemctl reload apache2

mod_evasive (Anti-DDoS)

# Instalar mod_evasive
sudo apt install libapache2-mod-evasive -y
sudo a2enmod evasive
# /etc/apache2/mods-available/evasive.conf
<IfModule mod_evasive20.c>
    DOSHashTableSize    3097
    DOSPageCount         2      # Máx. requisições por página
    DOSSiteCount         50     # Máx. requisições por site
    DOSPageInterval       1     # Intervalo em segundos
    DOSSiteInterval       1
    DOSBlockingPeriod    10     # Tempo de bloqueio (segundos)
    DOSEmailNotify   [email protected]
    DOSSystemCommand   "iptables -A INPUT -s %s -j DROP"
    DOSLogDir           "/var/log/mod_evasive"
</IfModule>

Configuração de Logs

Formatos de Log

# Formato combinado (padrão)
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

# Formato comum
LogFormat "%h %l %u %t \"%r\" %>s %b" common

# Formato com tempo de resposta
LogFormat "%h %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"" combined-with-time

# Formato JSON
LogFormat "{ \"time\":\"%t\", \"remote\":\"%h\", \"request\":\"%r\", \"status\": %>s, \"bytes\":%b, \"duration_us\":%D }" json

# Aplicar formato
CustomLog ${APACHE_LOG_DIR}/access.log combined-with-time
CustomLog ${APACHE_LOG_DIR}/access.json.log json

Logrotate

# /etc/logrotate.d/apache2
/var/log/apache2/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 640 adm adm
    sharedscripts
    postrotate
        if /etc/init.d/apache2 status > /dev/null ; then
            /etc/init.d/apache2 reload > /dev/null
        fi
    endscript
}
# Testar logrotate
sudo logrotate -d /etc/logrotate.d/apache2
sudo logrotate -f /etc/logrotate.d/apache2

VirtualHost com Logs Separados

<VirtualHost *:80>
    ServerName site.com
    DocumentRoot /var/www/site

    # Logs específicos do site
    ErrorLog  ${APACHE_LOG_DIR}/site.com/error.log
    CustomLog ${APACHE_LOG_DIR}/site.com/access.log combined

    # Log de erros separado por severidade
    LogLevel warn rewrite:trace3

    # Log de requisições lentas
    LogLevel info
    SetEnvIf Request_Time ">[0-9]*[5-9][0-9]{5}|[0-9]{7,}" slow-request
    CustomLog ${APACHE_LOG_DIR}/site.com/slow.log common env=slow-request
</VirtualHost>

Monitoramento

mod_status

# Habilitar status
sudo a2enmod status
# /etc/apache2/mods-available/status.conf
<Location /server-status>
    SetHandler server-status
    Require ip 127.0.0.1 ::1
    Require ip 192.168.1.0/24
    # Require all denied (se desejado)
</Location>

# Página estendida
ExtendedStatus On
# Verificar status via curl
curl http://127.0.0.1/server-status
curl http://127.0.0.1/server-status?auto

# Monitoramento com watch
watch -n 1 'curl -s http://127.0.0.1/server-status?auto'

mod_info

sudo a2enmod info
<Location /server-info>
    SetHandler server-info
    Require ip 127.0.0.1
</Location>
# Acesso
curl http://127.0.0.1/server-info

Reverse Proxy com mod_proxy

# Habilitar módulos de proxy
sudo a2enmod proxy proxy_http proxy_balancer proxy_ajp lbmethod_byrequests
# Proxy básico para backend
<VirtualHost *:80>
    ServerName app.exemplo.com

    ProxyRequests Off
    ProxyPreserveHost On

    <Location />
        ProxyPass http://localhost:3000/
        ProxyPassReverse http://localhost:3000/
    </Location>

    <Location /api>
        ProxyPass http://localhost:8080/
        ProxyPassReverse http://localhost:8080/
    </Location>

    ErrorLog ${APACHE_LOG_DIR}/proxy-error.log
    CustomLog ${APACHE_LOG_DIR}/proxy-access.log combined
</VirtualHost>
# Load Balancing com Proxy Balancer
<VirtualHost *:80>
    ServerName load.exemplo.com

    <Proxy balancer://cluster>
        BalancerMember http://backend1:8080 route=node1
        BalancerMember http://backend2:8080 route=node2
        BalancerMember http://backend3:8080 route=node3

        # Método de balanceamento
        ProxySet lbmethod=byrequests
        # byrequests (round-robin), bytraffic, bybusyness

        # Health checks
        ProxySet healthcheck=/

        # Sticky session
        ProxySet stickysession=ROUTEID
    </Proxy>

    ProxyPreserveHost On
    ProxyPass / balancer://cluster/
    ProxyPassReverse / balancer://cluster/
</VirtualHost>

Proxy AJP (Tomcat)

<VirtualHost *:80>
    ServerName java.exemplo.com

    ProxyPass / ajp://localhost:8009/
    ProxyPassReverse / ajp://localhost:8009/

    <Proxy *>
        Require all granted
    </Proxy>
</VirtualHost>

Troubleshooting

# Testar configuração
sudo apache2ctl configtest

# Verificar erros de sintaxe em todos os arquivos
sudo apache2ctl -t

# Verificar módulos carregados
sudo apache2ctl -M

# Verificar VirtualHosts
sudo apache2ctl -S

# Debug de rewrite
sudo tail -f /var/log/apache2/error.log | grep -E "\[rewrite"

# Testar com diferentes métodos HTTP
curl -X PURGE http://localhost/cache
curl -X OPTIONS http://localhost -I

# Verificar conexões ativas
ss -tlnp | grep 80

# Analisar logs em tempo real
sudo tail -f /var/log/apache2/access.log | goaccess --log-format=COMBINED -

# Verificar workers ativos
ps aux | grep apache2 | wc -l

Lab: Servidor Apache em Produção

Configure um servidor Apache completo para produção com segurança, monitoramento e proxy reverso.

# 1. Hardening básico
sudo a2dismod autoindex info userdir
sudo a2enconf security

cat << 'SEC' | sudo tee /etc/apache2/conf-available/hardening.conf
ServerTokens Prod
ServerSignature Off
TraceEnable Off
FileETag None
SEC

sudo a2enconf hardening

# 2. Configurar mod_status
sudo a2enmod status
cat << 'STAT' | sudo tee /etc/apache2/mods-available/status.conf
<Location /server-status>
    SetHandler server-status
    Require ip 127.0.0.1
</Location>
ExtendedStatus On
STAT

# 3. Configurar logs rotacionados
sudo mkdir -p /var/log/apache2/site.com/
cat << 'LOG' | sudo tee /etc/apache2/conf-available/log-format.conf
LogFormat "%h %l %u %t \"%r\" %>s %b %D" with-time
LOG

# 4. Configurar reverse proxy
sudo a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests
cat << 'RPX' | sudo tee /etc/apache2/sites-available/reverse-proxy.conf
<VirtualHost *:80>
    ServerName app.exemplo.com
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    ErrorLog ${APACHE_LOG_DIR}/app-error.log
    CustomLog ${APACHE_LOG_DIR}/app-access.log with-time
</VirtualHost>
RPX

# 5. Aplicar todas as configurações
sudo a2enconf log-format
sudo a2ensite reverse-proxy.conf
sudo apache2ctl configtest && sudo systemctl reload apache2

# 6. Verificar hardening
curl -I http://localhost | grep -E "Server|X-"

# 7. Verificar status
curl http://127.0.0.1/server-status?auto

Segurança em produção é uma camada, não uma feature. Combine hardening do Apache, WAF (mod_security), rate limiting (mod_evasive), monitoramento contínuo e logs centralizados para um ambiente verdadeiramente seguro.