Por que a segurança de um servidor precisa ser tratada em camadas

Um servidor conectado à internet recebe tentativas automatizadas de acesso, varreduras de portas, exploração de serviços vulneráveis e ataques contra aplicações. Não é necessário que o sistema seja conhecido para entrar em listas de alvos: endereços IP públicos são examinados continuamente por robôs.

Proteger um servidor não significa instalar um firewall e considerar o trabalho encerrado. A segurança depende de várias camadas: reduzir serviços expostos, corrigir vulnerabilidades, controlar identidades, limitar privilégios, criptografar comunicações, registrar eventos, manter cópias de segurança e testar a recuperação.

Este guia usa Debian e Ubuntu com systemd como referência. Os comandos devem ser adaptados à versão, aos serviços instalados e à arquitetura de rede. Antes de aplicar mudanças em produção, mantenha acesso ao console do provedor ou uma sessão administrativa alternativa. Uma regra de firewall ou alteração de SSH incorreta pode bloquear o próprio administrador.

Entenda a superfície de ataque

A superfície de ataque é o conjunto de pontos pelos quais alguém pode tentar interagir com o sistema. Ela inclui portas de rede, serviços, aplicações web, APIs, painéis administrativos, contas, chaves SSH, containers, dependências e integrações externas.

O princípio central do hardening é reduzir essa superfície: instalar somente o necessário, desativar serviços não utilizados, restringir a origem das conexões e executar cada componente com o menor privilégio possível.

  • Confidencialidade: impedir que dados sejam acessados por pessoas ou processos não autorizados.
  • Integridade: evitar alterações não autorizadas em arquivos, configurações e registros.
  • Disponibilidade: manter o serviço operacional e preparado para falhas e ataques.
  • Rastreabilidade: registrar eventos suficientes para investigar incidentes.

Faça um inventário antes de alterar configurações

Não comece fechando portas aleatoriamente. Primeiro descubra o que está instalado, quais serviços estão ativos e quais interfaces estão expostas.

cat /etc/os-release
uname -r
hostnamectl
ip -br address
ip route
systemctl --type=service --state=running
sudo ss -tulpn
sudo systemctl --failed

O comando ss lista sockets TCP e UDP. A opção -l mostra sockets em escuta, -t e -u selecionam TCP e UDP, -p mostra o processo quando permitido e -n evita resolução de nomes.

Para investigar um serviço específico:

sudo systemctl status ssh
sudo journalctl -u ssh --since "24 hours ago"
sudo systemctl cat ssh

Em algumas distribuições o serviço pode se chamar sshd. Não desative um serviço apenas porque seu nome parece desconhecido: identifique sua função e dependências primeiro.

Portas TCP e UDP: descubra o que está realmente exposto

Uma porta é um identificador lógico usado pelo sistema operacional para encaminhar tráfego a um serviço. TCP estabelece uma conexão e oferece entrega ordenada; UDP envia datagramas sem estabelecer uma conexão equivalente. Ambos podem ser usados por serviços legítimos e ambos podem ampliar a superfície de ataque.

PortaUso comumOrientação
22/TCPSSHRestringir por IP ou VPN sempre que possível.
80/TCPHTTPManter apenas se necessário para redirecionamento ou validação.
443/TCPHTTPSExpor para aplicações web públicas.
53/TCP e UDPDNSExpor somente se o servidor operar DNS.
123/UDPNTPNão transformar o host em servidor NTP público sem necessidade.
3306/TCPMySQL/MariaDBNão expor publicamente; preferir rede privada ou socket local.
5432/TCPPostgreSQLRestringir a aplicações e redes autorizadas.
6379/TCPRedisNão expor diretamente à internet.

Essas são portas padrão, não uma lista completa. Serviços podem usar portas diferentes, e uma porta aberta não prova, por si só, que existe uma vulnerabilidade. O risco depende do serviço, versão, configuração, autenticação e exposição.

Faça uma verificação externa somente em sistemas próprios ou com autorização explícita. A partir de uma máquina de auditoria autorizada:

nmap -Pn -sS -sV -p- IP_DO_SEU_SERVIDOR

O parâmetro -p- examina todas as portas TCP. Para UDP, a verificação é mais lenta e exige privilégios em muitos ambientes:

sudo nmap -Pn -sU --top-ports 100 IP_DO_SEU_SERVIDOR

Compare o resultado externo com o inventário local. Se uma porta aparece externamente, mas não deveria, verifique firewall do sistema, regras do provedor, balanceadores, NAT, containers e outros equipamentos de rede.

Configure um firewall com política explícita

O firewall deve permitir somente o tráfego necessário. Em Ubuntu, o UFW oferece uma interface mais simples; nftables permite controle mais detalhado. Evite administrar simultaneamente várias ferramentas que escrevem regras incompatíveis sem entender a cadeia de processamento de pacotes.

Exemplo com UFW para um servidor web que aceita SSH apenas de um endereço administrativo fixo:

sudo apt update
sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status numbered
sudo ufw enable

Substitua 203.0.113.10 pelo IP administrativo real. O endereço usado no exemplo pertence a uma faixa reservada para documentação. Se o IP administrativo for dinâmico, considere VPN ou outro mecanismo de acesso controlado. Antes de habilitar o firewall remotamente, confirme a regra SSH e mantenha o console do provedor disponível.

Se SSH precisar aceitar conexões de qualquer origem, a regra pode ser sudo ufw allow 22/tcp, mas isso aumenta a exposição e exige autenticação forte, atualizações e monitoramento.

Para inspecionar regras nftables existentes:

sudo nft list ruleset

Não substitua o ruleset inteiro com um exemplo genérico. Uma máquina pode depender de regras de VPN, IPv6, encaminhamento, Kubernetes, Docker ou NAT. Planeje a política, valide em ambiente de teste e tenha um procedimento de rollback.

O firewall local não substitui o firewall do provedor. Quando disponível, configure também regras de entrada na nuvem ou no painel de hospedagem, permitindo somente portas e origens necessárias.

Proteja o SSH sem perder o acesso administrativo

SSH é um dos principais caminhos de administração remota. Prefira autenticação por chave pública, contas individuais e privilégios via sudo. Não compartilhe a conta root entre administradores.

Na estação administrativa, gere uma chave moderna, se ainda não houver uma:

ssh-keygen -t ed25519 -a 64
ssh-copy-id usuario@IP_DO_SERVIDOR
ssh usuario@IP_DO_SERVIDOR

Depois de confirmar que a chave funciona em uma nova sessão, avalie uma configuração em /etc/ssh/sshd_config.d/ ou no arquivo principal, conforme a distribuição:

PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
MaxAuthTries 3
AllowUsers usuario_admin

Essas opções são um exemplo de política, não uma receita universal. Confirme se há outros métodos de autenticação, automações, contas de serviço ou requisitos de recuperação antes de desabilitar senhas. Em ambientes que usam MFA via PAM ou autenticação interativa, desabilitar KbdInteractiveAuthentication pode quebrar o fluxo.

Valide a sintaxe antes de recarregar:

sudo sshd -t
sudo sshd -T | grep -E 'permitrootlogin|pubkeyauthentication|passwordauthentication|maxauthtries'
sudo systemctl reload ssh

Mantenha a sessão atual aberta e teste uma segunda conexão em outro terminal. Só encerre a sessão antiga depois de confirmar o novo acesso. Em sistemas nos quais a unidade se chama sshd, use esse nome no systemctl.

Quando possível, limite SSH a uma VPN, rede administrativa ou lista de IPs confiáveis. Alterar a porta padrão pode reduzir ruído automatizado, mas não é uma defesa real contra invasões e não substitui autenticação forte.

Organize usuários, grupos e permissões

Serviços e aplicações não devem executar como root sem necessidade. Crie contas específicas, remova usuários obsoletos e conceda privilégios administrativos somente a quem precisa.

getent passwd
getent group sudo
sudo last
sudo lastb

Verifique permissões de arquivos sensíveis:

sudo stat /etc/shadow /etc/ssh/sshd_config
sudo find /var/www -xdev -type f -perm -0002 -print
sudo find /var/www -xdev -type d -perm -0002 -print

Não aplique chmod -R 755 ou chmod -R 644 em uma aplicação inteira. Diretórios, arquivos executáveis, arquivos de configuração, uploads e segredos têm necessidades diferentes. O usuário do servidor web deve ter escrita apenas nos diretórios que realmente precisam receber arquivos, como uma pasta de uploads ou cache, e não em todo o código.

Segredos, chaves privadas e arquivos de ambiente devem ficar fora da raiz pública do site, com permissões restritas e sem inclusão em repositórios. Revise também backups, arquivos temporários e logs que possam conter tokens ou dados pessoais.

Mantenha o sistema corrigido e reduza serviços desnecessários

Atualizações de segurança corrigem falhas conhecidas que podem ser exploradas por atacantes. Defina uma rotina para acompanhar avisos de segurança, aplicar atualizações e reiniciar quando necessário.

sudo apt update
sudo apt list --upgradable
sudo apt upgrade
sudo apt autoremove

Em Debian e Ubuntu, o pacote unattended-upgrades pode automatizar atualizações selecionadas. Revise a política, monitore os logs e planeje reinicializações para atualizações de kernel e bibliotecas que exigem reinício.

sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades
systemctl status unattended-upgrades

Não confunda atualização automática com gestão de mudanças. Em produção, mantenha inventário, janela de manutenção, cópias de segurança e testes de regressão. Verifique também o ciclo de suporte da versão do sistema operacional e planeje migrações antes do fim do suporte.

Liste serviços habilitados e desative somente os que foram identificados como desnecessários:

systemctl list-unit-files --type=service --state=enabled
sudo systemctl disable --now nome-do-servico

Use proteção contra tentativas repetidas de autenticação

Fail2ban analisa registros e pode aplicar bloqueios temporários a endereços que repetem padrões de falha. Ele ajuda a reduzir tentativas automatizadas, mas não corrige senhas fracas, serviços vulneráveis ou credenciais vazadas.

sudo apt install fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status

Em sistemas nos quais o SSH registra eventos no journal do systemd, uma configuração de jail pode usar o backend systemd:

[sshd]
enabled = true
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h

Salve a configuração local em /etc/fail2ban/jail.d/sshd.local ou em um arquivo local equivalente, conforme a distribuição. Com backend systemd, não configure logpath para a mesma jail: esse backend lê o journal. Para jails que analisam arquivos de log, use um backend de arquivo compatível e informe o caminho correto.

sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Monitore falsos positivos e garanta que endereços administrativos não sejam bloqueados por engano. Fail2ban é uma camada complementar, não substitui VPN, chaves SSH, MFA e firewall.

Proteja Nginx, Apache, PHP e aplicações web

Servidores web devem expor apenas os endpoints necessários. Desative listagem de diretórios, evite publicar arquivos de configuração, arquivos de backup, repositórios Git, dumps SQL e arquivos de ambiente. Configure limites de tamanho, timeouts e cabeçalhos de segurança de acordo com a aplicação.

No PHP, mantenha uma versão suportada, atualize dependências e evite exibir erros internos ao visitante em produção. Configure logs privados, validação de entrada, consultas parametrizadas, proteção CSRF quando aplicável, controle de sessão e autorização no servidor.

Verifique a configuração do Nginx antes de recarregar:

sudo nginx -t
sudo systemctl reload nginx

Para Apache:

sudo apachectl configtest
sudo systemctl reload apache2

Não confie apenas em validação no navegador. Regras de autorização precisam ser verificadas no backend em cada operação sensível. Uploads devem validar tipo real, tamanho, extensão permitida e nome de arquivo; quando possível, armazene-os fora da raiz pública e sirva-os por um controlador com autorização.

Não exponha bancos de dados e caches sem necessidade

MySQL, MariaDB, PostgreSQL e Redis normalmente devem aceitar conexões apenas de localhost, de uma rede privada ou de hosts de aplicação explicitamente autorizados. Evite liberar portas de banco para toda a internet.

Use contas diferentes por aplicação, privilégios mínimos, senhas exclusivas, TLS quando o tráfego atravessar redes não confiáveis e backups criptografados. Remova contas de teste e revise permissões concedidas a usuários antigos.

Confira os sockets em escuta e a configuração de bind do serviço. Alterar o bind para um endereço privado pode ser adequado, mas confirme a topologia e as regras de firewall antes de reiniciar o banco. Não publique Redis sem autenticação e isolamento de rede; autenticação isolada não torna segura uma exposição desnecessária.

Docker, containers e túneis: atenção aos caminhos alternativos

Containers não eliminam a responsabilidade de proteger o host. Atualize imagens, prefira imagens mínimas e confiáveis, fixe versões quando a reprodutibilidade for importante, não execute como root sem necessidade e evite montar o socket do Docker dentro de aplicações comuns. O acesso ao socket do Docker equivale, na prática, a um alto nível de controle sobre o host.

Revise portas publicadas:

docker ps --format 'table {{.Names}}\t{{.Ports}}'
docker inspect nome_do_container
sudo ss -tulpn

Uma publicação como -p 8080:80 pode disponibilizar a porta em todas as interfaces do host. Quando o serviço deve ser acessível somente localmente por um proxy reverso, prefira um bind explícito como -p 127.0.0.1:8080:80.

Há uma armadilha importante: regras de publicação de portas do Docker podem desviar o tráfego antes das cadeias usadas pelo UFW. Portanto, não presuma que uma porta publicada está protegida apenas porque o status do UFW parece correto. Revise o backend de firewall do Docker e as regras efetivas do host. Em instalações que usam iptables, a cadeia DOCKER-USER é o ponto documentado para regras adicionais de filtragem de tráfego encaminhado. Não edite diretamente as regras que o Docker cria nem desative seu gerenciamento sem uma política substituta testada.

Um Cloudflare Tunnel pode evitar a necessidade de expor diretamente algumas portas HTTP, mas não torna o host invulnerável. Confirme que não existem serviços publicados por outro endereço, IPv6, regras antigas, painéis administrativos ou caminhos alternativos que contornem o túnel. Proteja também o acesso ao painel e às credenciais do agente.

Configure HTTPS, certificados e DNS corretamente

Aplicações públicas devem usar HTTPS. TLS protege a comunicação entre cliente e servidor, mas não corrige falhas de autorização, código vulnerável ou comprometimento do host.

Use certificados válidos, renove-os automaticamente e monitore a expiração. Em Nginx, teste a configuração e confirme que os protocolos habilitados são compatíveis com clientes atuais. TLS 1.2 e TLS 1.3 são referências comuns para configurações modernas, mas a política exata deve considerar a biblioteca e os clientes atendidos.

sudo certbot renew --dry-run
openssl s_client -connect exemplo.com:443 -servername exemplo.com

Proteja chaves privadas com permissões restritas. Se usar proxy reverso ou CDN, configure corretamente os cabeçalhos de IP encaminhado e confie neles somente quando a conexão vier de proxies conhecidos. Uma configuração incorreta pode permitir falsificação de IP em logs ou controles de acesso.

Revise registros DNS, subdomínios abandonados e apontamentos para serviços removidos. Um registro esquecido pode permitir sequestro de subdomínio se o serviço de destino puder ser reivindicado por terceiros.

Monitore logs, integridade e comportamento do servidor

Segurança exige visibilidade. Colete logs de autenticação, firewall, servidor web, banco de dados, aplicações e sistema. Centralize registros quando possível, restrinja seu acesso e defina retenção compatível com requisitos legais e operacionais.

sudo journalctl -p warning --since "24 hours ago"
sudo journalctl -u ssh --since "24 hours ago"
sudo journalctl -k --since "24 hours ago"
df -h
free -h
uptime
sudo ss -s

Monitore tentativas de login, criação de usuários, alterações de privilégios, processos inesperados, uso anormal de CPU e memória, espaço em disco, falhas de serviço, certificados próximos do vencimento e mudanças em arquivos críticos.

Ferramentas como auditd podem registrar eventos específicos do sistema. Prometheus e Grafana podem ajudar com métricas e painéis; agentes e coletores devem ser protegidos e não devem expor suas interfaces administrativas publicamente. Um painel bonito não substitui alertas acionáveis nem uma pessoa responsável por responder a eles.

Defina alertas com limites e contexto. Alertar sobre qualquer pico isolado gera fadiga; alertar sobre padrões persistentes, falhas repetidas ou alterações críticas tende a ser mais útil.

Backups e recuperação: prove que consegue restaurar

Backup que nunca foi restaurado é uma esperança, não uma estratégia testada. Mantenha cópias em locais separados do servidor de produção, criptografe os repositórios, restrinja credenciais e adote retenção adequada. Quando possível, use cópias imutáveis ou com proteção contra exclusão pelo mesmo usuário que administra o servidor.

O modelo 3-2-1 é uma referência prática: três cópias dos dados, em pelo menos dois tipos de mídia ou ambientes, com uma cópia fora do local principal. Ajuste a estratégia ao risco, custo e objetivo de recuperação.

Exemplo com Restic. Guarde a senha em um mecanismo seguro de segredos, não em scripts versionados ou no histórico do shell:

export RESTIC_REPOSITORY=/caminho/para/repositorio
read -s RESTIC_PASSWORD
export RESTIC_PASSWORD
restic init
restic backup /etc /var/www /srv/dados
restic snapshots
restic check

O comando restic init deve ser executado apenas na criação inicial do repositório. Para testar a recuperação, escolha um snapshot e restaure para um diretório temporário:

restic restore ID_DO_SNAPSHOT --target /tmp/restic-restore
find /tmp/restic-restore -maxdepth 3 -type f | head

Valide integridade, permissões, propriedade dos arquivos e consistência de bancos de dados. Para bancos, prefira mecanismos de dump ou backup nativo consistentes com o produto. Documente RPO, o quanto de dados pode ser perdido, e RTO, quanto tempo o serviço pode ficar indisponível.

Plano de resposta a incidentes

Quando houver suspeita de invasão, evite apagar evidências ou reinstalar imediatamente sem registrar o que aconteceu. A prioridade é limitar o dano, preservar informações e recuperar o serviço com segurança.

  1. Identifique: registre horário, alertas, contas afetadas, processos, conexões e serviços envolvidos.
  2. Contenha: isole o host ou bloqueie o caminho comprometido sem destruir evidências relevantes.
  3. Preserve: proteja logs, snapshots e imagens de disco conforme a criticidade e os requisitos legais.
  4. Revogue: troque credenciais, chaves, tokens e segredos que possam ter sido expostos, usando uma estação confiável.
  5. Erradique: corrija a causa raiz, remova persistência maliciosa e reinstale componentes quando não houver confiança na integridade.
  6. Recupere: restaure a partir de cópia conhecida, aplique correções e valide o ambiente antes de reabrir o acesso.
  7. Aprenda: documente a linha do tempo e as ações preventivas para evitar recorrência.

Se houver dados pessoais, dados financeiros ou obrigação regulatória, envolva as pessoas responsáveis por segurança, privacidade e jurídico. Não prometa que um sistema está limpo apenas porque um antivírus não encontrou arquivos suspeitos.

Laboratório: checklist de validação antes de colocar em produção

Use esta sequência em uma máquina de teste ou em uma janela de manutenção planejada. Registre o estado anterior e valide cada etapa.

  • Inventário: sistema, kernel, serviços, portas locais e portas vistas externamente.
  • Atualizações: pacotes corrigidos, política de atualização e plano de reinicialização.
  • Firewall: política de entrada restritiva, IPv4 e IPv6 avaliados, regras do provedor revisadas.
  • SSH: chave testada em uma segunda sessão, root remoto bloqueado conforme a política e recuperação administrativa disponível.
  • Permissões: contas antigas removidas, privilégios mínimos e segredos fora da raiz pública.
  • Aplicação: dependências atualizadas, erros ocultos do visitante, uploads controlados e autorização validada no backend.
  • Containers: portas publicadas revisadas, privilégios reduzidos e regras efetivas verificadas.
  • Monitoramento: logs acessíveis, alertas testados e espaço em disco acompanhado.
  • Backup: cópia recente, repositório verificado e restauração concluída em ambiente temporário.
  • Incidentes: contatos, responsáveis, procedimento de isolamento e recuperação documentados.

Depois de cada alteração crítica, valide o serviço e registre o resultado. Para configurações de SSH, use sshd -t; para Nginx, nginx -t; para Apache, apachectl configtest; para UFW, ufw status verbose; para Fail2ban, fail2ban-client status. A validação local deve ser complementada por um teste externo autorizado.

Erros comuns que enfraquecem a segurança

  • Confiar apenas em mudar a porta SSH: scanners identificam serviços em portas não padrão.
  • Bloquear portas sem inventário: pode interromper VPN, DNS, monitoramento ou aplicações.
  • Supor que UFW controla todas as portas publicadas pelo Docker: o caminho de rede pode contornar as cadeias usuais do UFW.
  • Desabilitar senha SSH antes de testar a chave em outra sessão: pode causar bloqueio administrativo.
  • Usar permissões recursivas genéricas: pode expor segredos ou quebrar aplicações.
  • Instalar Fail2ban e nunca verificar suas jails: o serviço pode estar ativo sem analisar a fonte de log esperada.
  • Manter backups no mesmo host e com a mesma credencial administrativa: um invasor pode apagar produção e cópias.
  • Considerar HTTPS sinônimo de aplicação segura: TLS protege o transporte, não a lógica do sistema.
  • Não testar restauração: falhas de backup só aparecem quando a recuperação é necessária.

Conclusão

Um servidor seguro é resultado de manutenção contínua, não de uma configuração isolada. Comece pelo inventário, reduza serviços e portas, aplique atualizações, restrinja SSH, configure firewall com cuidado, proteja aplicações e bancos, monitore eventos e mantenha backups restauráveis.

O objetivo do hardening não é tornar o servidor impossível de atacar. É reduzir oportunidades, dificultar a exploração, detectar comportamentos anormais e garantir que a operação consiga se recuperar quando algo falhar. Revise essas medidas periodicamente e sempre que a arquitetura mudar.

Referências oficiais e documentação técnica