Linux Server Hardening Checklist 2026: SSH, Firewall e Kernel

Um servidor Linux recém-instalado vem com dezenas de serviços activos, root acessível por SSH e kernel em configuração permissiva. Este guia percorre 12 secções práticas — desde o endurecimento do SSH ao sysctl do kernel, fail2ban, AppArmor/SELinux e auditoria Lynis — com comandos reais para Ubuntu, Debian, RHEL, AlmaLinux e Rocky Linux.

⚠ Aplicar primeiro em staging

Antes de endurecer qualquer servidor em produção, testa todos os passos num ambiente de staging idêntico. Garante que tens acesso à consola (VNC, IPMI ou painel da VPS) — se bloqueares o SSH por engano, a consola é a única forma de recuperar o acesso. Faz uma cópia de segurança do /etc/ssh/sshd_config antes de qualquer alteração.

1. Superfície de Ataque

Um servidor Linux recém-instalado — seja Ubuntu, Debian, RHEL, AlmaLinux ou Rocky — expõe uma superfície de ataque considerável por defeito. Eis o que está acessível antes de qualquer hardening:

  • SSH na porta 22 — o primeiro alvo de bots que fazem brute-force a root/admin/redis com dicionários de passwords comuns.
  • Login de root por SSH — em Ubuntu/Debian vem desactivado por defeito (usa sudo), mas em RHEL/CentOS o PermitRootLogin pode estar activo consoante a imagem.
  • Serviços desnecessários — rpcbind, avahi-daemon, cups, postfix, dnsmasq abrem portas sem utilidade para a maioria dos servidores.
  • Kernel permissivo — redireccionamentos ICMP, IP forwarding, kptr expose e core dumps activos por defeito.
  • Sem actualizações automáticas — unattended-upgrades ou dnf-automatic não vêm configurados; patches de segurança ficam por aplicar.
  • Sem MAC — AppArmor pode estar em complain mode; SELinux pode estar disabled ou permissive.
  • IPv6 activo — se não usas IPv6, todas as portas abertas em IPv4 também estão abertas em IPv6, frequentemente esquecidas na firewall.
  • /dev/shm com exec — partilha de memória montada sem noexec/nosuid/nodev, permitindo execução de binários aí colocados.
  • Sem logrotate ou rotação configurada — logs podem crescer sem limite e encher o disco em produção.

Cada ponto acima é corrigido nas secções seguintes. A ordem recomendada é: SSH → firewall → actualizações → fail2ban → kernel → MAC → serviços → /dev/shm + IPv6 → auditoria.

2. Cenários

O nível de hardening depende do contexto. Nem todos os passos se aplicam a todos os servidores — adapta conforme o cenário:

Cenário Prioridade Notas
VPS nova (cloud) Alta — SSH exposto à Internet desde o minuto 1 Aplicar SSH + firewall + fail2ban antes de instalar qualquer serviço. Bots atacam IPs novos em minutos.
Servidor on-premise Média — atrás de router/firewall de rede Hardening de kernel e MAC continua necessário — firewall de rede não substitui defesa em profundidade.
Staging com IP público Alta — mesmo que produção Staging com IP público é alvo tão válido como produção. Aplicar a mesma checklist completa.
Pós-migração Alta — serviços herdados podem estar activos Rever serviços activos com ss -tulpn — migrações arrastam postfix, rpcbind, etc.

3. Endurecer SSH

O SSH é a porta de entrada mais atacada em servidores Linux. Os três passos essenciais: usar chaves Ed25519 em vez de passwords, proibir login de root e mudar a porta padrão.

Gerar chave Ed25519 na máquina cliente

# Gerar chave Ed25519 (mais rápida e segura que RSA 2048)
ssh-keygen -t ed25519 -a 100 -C "[email protected]"

# Copiar a chave pública para o servidor
ssh-copy-id -i ~/.ssh/id_ed25519.pub utilizador@servidor

# Testar login sem password
ssh utilizador@servidor

Configurar sshd_config

# Backup do ficheiro original
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# Editar configuração
sudo nano /etc/ssh/sshd_config

Parâmetros a alterar ou adicionar no /etc/ssh/sshd_config:

Port 22022
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
X11Forwarding no
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers utilizador

Recarregar e verificar

# Validar sintaxe antes de recarregar (NÃO saltar este passo)
sudo sshd -t

# Recarregar sshd (NÃO reiniciar — mantém sessão actual)
sudo systemctl reload sshd

# Testar ligação na nova porta ANTES de fechar a sessão actual
ssh -p 22022 utilizador@servidor

ⓘ Importante

Nunca feches a sessão SSH actual sem primeiro testar a nova configuração numa janela separada. Se algo estiver mal configurado, a sessão antiga continua aberta para corrigir.

4. Firewall

A firewall deve seguir política default deny: tudo é proibido excepto o que for explicitamente permitido. O Ubuntu/Debian usa UFW; o RHEL/AlmaLinux/Rocky usa firewalld.

UFW (Ubuntu/Debian)

sudo apt update && sudo apt install -y ufw

# Politica default: deny incoming, allow outgoing
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Permitir SSH na porta configurada (usar a porta do sshd_config)
sudo ufw allow 22022/tcp comment 'SSH'

# Permitir HTTP e HTTPS se for servidor web
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'

# Activar firewall
sudo ufw enable

# Verificar regras
sudo ufw status verbose

firewalld (RHEL/AlmaLinux/Rocky)

sudo dnf install -y firewalld
sudo systemctl enable --now firewalld

# Adicionar SSH na porta configurada
sudo firewall-cmd --permanent --add-port=22022/tcp

# Adicionar HTTP e HTTPS se necessario
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

# Recarregar e verificar
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Se mudaste a porta SSH para 22022, garante que a firewall permite essa porta antes de recarregar o sshd — caso contrário ficas sem acesso remoto.

5. Actualizações Automáticas

Manter o servidor actualizado é a defesa mais eficaz contra exploits conhecidos. Configurar actualizações automáticas apenas de segurança evita quebras de produção por updates não testados.

unattended-upgrades (Debian/Ubuntu)

sudo apt install -y unattended-upgrades apt-listchanges

# Configurar apenas security updates
sudo dpkg-reconfigure -plow unattended-upgrades

Verifica o ficheiro /etc/apt/apt.conf.d/50unattended-upgrades e garante que apenas a origem de segurança está activa:

Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}-security";
};

// Reboot automatico se necessario (kernel upgrade)
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";

dnf-automatic (RHEL/AlmaLinux/Rocky)

sudo dnf install -y dnf-automatic

# Configurar apenas security updates
sudo sed -i 's/^upgrade_type.*/upgrade_type = security/' /etc/dnf/automatic.conf
sudo sed -i 's/^apply_updates.*/apply_updates = yes/' /etc/dnf/automatic.conf

# Activar
sudo systemctl enable --now dnf-automatic.timer

# Verificar timer
sudo systemctl status dnf-automatic.timer

6. fail2ban

O fail2ban monitoriza logs de autenticação e bloqueia automaticamente IPs que falham repetidas vezes. É a camada que complementa a firewall contra brute-force SSH.

# Ubuntu/Debian
sudo apt install -y fail2ban

# RHEL/AlmaLinux/Rocky
sudo dnf install -y fail2ban fail2ban-firewalld

# Criar configuracao local (NAO editar jail.conf directamente)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Configuração da jail SSH no /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = 22022
filter = sshd
logpath = /var/log/auth.log
backend = systemd
maxretry = 3
findtime = 600
bantime = 3600
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24

Parâmetros: bantime = duração do banimento em segundos (3600 = 1 hora); findtime = janela de tempo para contar tentativas (600 = 10 minutos); maxretry = tentativas antes de banir. Em RHEL, substitui logpath = /var/log/auth.log por logpath = %(sshd_log)s e usa backend = systemd.

# Reiniciar e activar
sudo systemctl restart fail2ban
sudo systemctl enable fail2ban

# Verificar estado da jail
sudo fail2ban-client status sshd

# Verificar IPs banidas
sudo fail2ban-client status sshd | grep "Banned IP"

7. Kernel sysctl Hardening

O kernel Linux traz por defeito configurações pensadas para routers e workstations, não para servidores. Endurecer via sysctl reduz a superfície de ataque ao nível da pilha de rede e do próprio kernel.

Cria o ficheiro /etc/sysctl.d/99-hardening.conf:

sudo nano /etc/sysctl.d/99-hardening.conf

Conteúdo recomendado para um servidor que não é router:

# Redireccionamentos ICMP — desactivar
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# IP forwarding — desactivar se NAO for router
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# Proteccao SYN flood
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

# ICMP broadcast (smurf attack)
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Log packets with impossible addresses
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# Reverse path filtering
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Kernel hardening
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1
kernel.perf_event_paranoid = 2
kernel.yama.ptrace_scope = 1

# Desactivar core dumps de SUID
fs.suid_dumpable = 0

# Proteccao contra hardlinks/hardlinks
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
fs.protected_fifos = 2
fs.protected_regular = 2
# Aplicar sem reiniciar
sudo sysctl --load /etc/sysctl.d/99-hardening.conf

# Verificar
sudo sysctl net.ipv4.conf.all.send_redirects
sudo sysctl kernel.kptr_restrict
sudo sysctl fs.suid_dumpable

8. AppArmor/SELinux

Mandatory Access Control (MAC) restringe o que cada processo pode fazer, mesmo com root. Ubuntu/Debian usa AppArmor; RHEL/AlmaLinux/Rocky usa SELinux. Ambos devem estar em modo enforcing em produção.

AppArmor (Ubuntu/Debian)

# Verificar estado
sudo aa-status

# Instalar se nao estiver presente
sudo apt install -y apparmor apparmor-utils apparmor-profiles

# Garantir modo enforcing
sudo systemctl enable --now apparmor

# Activar perfis
sudo systemctl enable apparmor.service
sudo systemctl start apparmor.service

# Verificar perfis carregados
sudo apparmor_status | head -20

Para colocar um perfil individualmente em enforcing:

# Colocar perfil em enforcing
sudo aa-enforce /etc/apparmor.d/usr.sbin.mysqld

# Modo complain (apenas regista, nao bloqueia) — para testar
sudo aa-complain /etc/apparmor.d/usr.sbin.mysqld

# Listar perfis em complain
sudo aa-status | grep "complain"

SELinux (RHEL/AlmaLinux/Rocky)

# Verificar modo actual
getenforce

# Estado detalhado
sudo sestatus

# Activar enforcing (persistente)
sudo sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config

# Activar imediatamente (sem reboot)
sudo setenforce 1

# Verificar
getenforce

Diferença entre modos SELinux: disabled = completamente desactivado; permissive = regista violações mas não bloqueia (útil para testar políticas); enforcing = bloqueia violações. Em produção usa sempre enforcing — permissive só serve para diagnosticar problemas de política durante transição.

9. Desactivar Serviços Desnecessários

Cada serviço activo é uma porta aberta e um vetor de ataque potencial. Lista todos os serviços activos e desactiva os que não são necessários.

# Listar todos os servicos activos
systemctl list-unit-files --state=enabled

# Ver portas abertas e processos associados
ss -tulpn

# Desactivar servicos desnecessarios (se nao usados)
sudo systemctl disable --now rpcbind
sudo systemctl disable --now avahi-daemon
sudo systemctl disable --now cups
sudo systemctl disable --now postfix
sudo systemctl disable --now dnsmasq

# Remover pacotes completamente (opcional)
sudo apt purge -y rpcbind avahi-daemon cups postfix dnsmasq   # Debian/Ubuntu
sudo dnf remove -y rpcbind avahi cups postfix dnsmasq          # RHEL
Serviço Porta Desactivar se…
rpcbind 111 Não usas NFS ou NIS
avahi-daemon 5353 Servidor não precisa de mDNS/DNS-SD
cups 631 Não há impressoras no servidor
postfix 25 Não é servidor de email (usa relay externo)
dnsmasq 53 Não és servidor DNS local

10. /dev/shm e IPv6

Endurecer /dev/shm

A partilha de memória /dev/shm vem montada sem restrições por defeito. Adiciona noexec, nosuid e nodev para impedir execução de binários aí colocados:

# Verificar montagem actual
mount | grep /dev/shm

# Adicionar ao /etc/fstab
sudo nano /etc/fstab

# Linha a adicionar:
tmpfs /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0

# Remontar imediatamente
sudo mount -o remount /dev/shm

# Verificar
mount | grep /dev/shm

Desactivar IPv6 (se não usado)

Se o servidor não usa IPv6, desactivá-lo fecha todas as portas IPv6 que a firewall pode estar a esquecer. Adiciona ao ficheiro /etc/sysctl.d/99-disable-ipv6.conf:

sudo nano /etc/sysctl.d/99-disable-ipv6.conf

# Conteudo:
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

# Aplicar
sudo sysctl --load /etc/sysctl.d/99-disable-ipv6.conf

# Verificar
cat /proc/sys/net/ipv6/conf/all/disable_ipv6

11. Auditoria Lynis

O Lynis é uma ferramenta de auditoria de segurança open-source que analisa o sistema e gera um relatório com recomendações e um hardening index (pontuação de 0 a 100).

# Ubuntu/Debian
sudo apt install -y lynis

# RHEL/AlmaLinux/Rocky
sudo dnf install -y lynis

# Executar auditoria completa
sudo lynis audit system

# Ou auditoria apenas para visualizar (sem escrever logs)
sudo lynis audit system --quick

O relatório é guardado em /var/log/lynis.log e os dados de auditoria em /var/log/lynis-report.dat. Interpreta os resultados:

  • Hardening index: pontuação de 0-100. <50 = fraco, 50-70 = razoável, 70-85 = bom, >85 = excelente.
  • Warnings: problemas críticos que devem ser corrigidos imediatamente.
  • Suggestions: recomendações de hardening ordenadas por prioridade (alta/média/baixa).
  • Tests skipped: testes não executados por falta de pacotes — instalar pacotes relevantes para cobertura completa.
# Ver apenas warnings e suggestions
sudo grep -E "Warning|Suggestion" /var/log/lynis.log

# Ver hardening index
sudo grep "hardening_index" /var/log/lynis-report.dat

# Ver todos os testes executados
sudo grep -c "^test=" /var/log/lynis-report.dat

12. Erros Comuns e Checklist

Erros Comuns

Problema Causa Solução
Ficas sem acesso SSH após mudar porta Firewall não permite a nova porta ou sshd não recarregou Aceder por consola VNC/IPMI; confirmar sshd -t sem erros e ufw allow porta/tcp antes de recarregar
fail2ban bane o teu próprio IP IP não está em ignoreip; testaste login errado repetidamente Adicionar IP a ignoreip; desbanir com fail2ban-client unban IP
SELinux bloqueia serviço após enabling Política não cobre o serviço; ficheiros com contexto errado Usar audit2allow para gerar política; ou permissive temporariamente
sysctl não aplica após reboot Ficheiro em local errado ou sintaxe incorrecta Confirmar ficheiro em /etc/sysctl.d/ com extensão .conf; validar com sysctl --load
AppArmor em complain mas não enforcing Perfil individual em modo complain Usar aa-enforce /etc/apparmor.d/perfil em cada perfil
unattended-upgrades instala pacotes que partem produção Allowed-Origins inclui updates normais além de security Manter apenas ${distro_id}:${distro_codename}-security em Allowed-Origins

Checklist de Hardening

  1. SSH: gerar chave Ed25519, copiar com ssh-copy-id, definir PermitRootLogin no, PasswordAuthentication no, porta não-standard, sshd -t antes de recarregar
  2. Firewall: UFW ou firewalld, política default deny, permitir apenas SSH/HTTP/HTTPS, activar
  3. Actualizações: instalar unattended-upgrades (Debian) ou dnf-automatic (RHEL), configurar apenas security updates
  4. fail2ban: instalar, configurar jail sshd com bantime/findtime/maxretry, adicionar ignoreip, activar
  5. Kernel sysctl: criar 99-hardening.conf, desactivar redireccionamentos, activar syncookies, kptr_restrict=2, suid_dumpable=0, aplicar com sysctl --load
  6. MAC: verificar AppArmor com aa-status ou SELinux com getenforce, activar enforcing
  7. Serviços: listar com systemctl list-unit-files --state=enabled, desactivar rpcbind/avahi/cups/postfix/dnsmasq, confirmar portas com ss -tulpn
  8. /dev/shm: adicionar noexec,nosuid,nodev ao fstab, remontar
  9. IPv6: se não usado, desactivar via sysctl em 99-disable-ipv6.conf
  10. Auditoria: instalar Lynis, executar lynis audit system, corrigir warnings, visar hardening index >70
  11. Logrotate: verificar /etc/logrotate.conf e configurações em /etc/logrotate.d/, testar com logrotate -d /etc/logrotate.conf

Artigos Relacionados