12 KiB
Guia de Hardening do Servidor Linux
Sobre este documento: Template explicativo das etapas de hardening aplicadas em servidores Ubuntu 24.04 LTS. Substitua os valores entre
<ANGULARES>pelos dados do servidor alvo antes de executar.
Variáveis a Substituir
| Placeholder | Descrição | Exemplo |
|---|---|---|
<USUARIO_ADMIN> |
Nome do usuário administrador a criar | deploy, sysadmin |
<SEU_EMAIL> |
E-mail do responsável (usado como comentário na chave SSH) | admin@empresa.com |
<CHAVE_PUBLICA_SSH> |
Chave pública SSH ed25519 do seu laptop | ssh-ed25519 AAAA... |
<IP_DO_SERVIDOR> |
IP público do servidor | 203.0.113.10 |
<CHAVE_PUBLICA_WG> |
Chave pública WireGuard gerada no servidor | resultado de wg pubkey |
<IP_TUNEL_VPN>/<PREFIXO> |
IP atribuído ao servidor dentro da VPN | 10.14.0.2/16 |
<ENDPOINT_VPN> |
Endereço do servidor VPN (hostname:porta) | servidor.vpn.com:51820 |
<CHAVE_PUBLICA_PEER_VPN> |
Chave pública do servidor VPN (fornecida pelo provedor) | resultado do painel da VPN |
<DNS_PRIMARIO> |
DNS primário fornecido pelo provedor VPN | 1.1.1.1 |
<DNS_SECUNDARIO> |
DNS secundário fornecido pelo provedor VPN | 8.8.8.8 |
1. Criação do Usuário Admin
useradd -m -s /bin/bash -G sudo <USUARIO_ADMIN>
echo "<USUARIO_ADMIN>:$(openssl rand -base64 32)" | chpasswd
mkdir -p /home/<USUARIO_ADMIN>/.ssh
chmod 700 /home/<USUARIO_ADMIN>/.ssh
echo "<CHAVE_PUBLICA_SSH>" > /home/<USUARIO_ADMIN>/.ssh/authorized_keys
chmod 600 /home/<USUARIO_ADMIN>/.ssh/authorized_keys
chown -R <USUARIO_ADMIN>:<USUARIO_ADMIN> /home/<USUARIO_ADMIN>/.ssh
echo "<USUARIO_ADMIN> ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/<USUARIO_ADMIN>
chmod 440 /etc/sudoers.d/<USUARIO_ADMIN>
Motivo: Servidores recém-provisionados têm apenas o usuário root ativo. Login direto como root é um vetor de ataque comum — bots fazem brute force em root 24/7. Criamos um usuário dedicado com chave SSH (ed25519), desabilitamos senha e bloqueamos login root no passo seguinte. O arquivo /etc/sudoers.d/<USUARIO_ADMIN> garante privilégios de administração sem precisar de senha (NOPASSWD), seguro pois a única forma de acesso é via chave SSH.
2. Atualização do Sistema e Instalação de Ferramentas
apt-get update -qq
apt-get upgrade -y -qq
apt-get install -y ufw fail2ban unattended-upgrades wireguard wireguard-tools
Motivo: Manter o sistema atualizado fecha vulnerabilidades conhecidas (CVEs). As ferramentas instaladas formam a base do hardening:
ufw: firewall simplificado sobre iptablesfail2ban: bane IPs após tentativas de força brutaunattended-upgrades: atualizações de segurança automáticaswireguard/wireguard-tools: VPN moderna e performática
3. Firewall UFW
ufw --force reset
ufw default deny incoming # bloqueia tudo que entra
ufw default allow outgoing # permite tudo que sai
ufw default deny forward # bloqueia pacotes roteados
ufw allow 22/tcp # permite SSH
ufw allow out on wg0 # permite tráfego VPN saindo
ufw allow in on wg0 # permite tráfego VPN entrando
ufw allow out 51820/udp # permite UDP para o endpoint VPN
ufw --force enable
Motivo: A política deny incoming fecha todas as portas por padrão — apenas o que for explicitamente permitido entra. A porta 22 é a única entrada permitida. As regras do wg0 e porta 51820/udp são necessárias para o túnel WireGuard funcionar.
Atenção: Verifique se está conectado ao servidor via SSH antes de habilitar o UFW. Execute os comandos em sequência e confirme que a porta 22 está liberada antes de rodar
ufw enable.
4. Hardening SSH
Arquivo: /etc/ssh/sshd_config
PermitRootLogin no # bloqueia login direto como root
PubkeyAuthentication yes # permite autenticação por chave
PasswordAuthentication no # desabilita senha (força uso de chave)
PermitEmptyPasswords no # bloqueia senhas vazias
KbdInteractiveAuthentication no
AllowUsers <USUARIO_ADMIN> # apenas o usuário admin pode fazer login
MaxAuthTries 3 # máximo 3 tentativas antes de desconectar
MaxSessions 5 # limita sessões simultâneas
LoginGraceTime 30 # 30s para autenticar, depois desconecta
ClientAliveInterval 300 # detecta conexões mortas em 5 minutos
ClientAliveCountMax 2
X11Forwarding no # desabilita X11 (desnecessário em servidor)
AllowAgentForwarding no # desabilita SSH agent forwarding
AllowTcpForwarding no # desabilita port forwarding via SSH
PermitTunnel no # desabilita criação de túneis SSH
LogLevel VERBOSE # log detalhado para auditoria
# Faça backup antes de aplicar
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d)
sshd -t # valida a config antes de aplicar
systemctl reload ssh # recarrega sem derrubar conexões ativas
Motivo: Cada linha desabilitada remove uma superfície de ataque. AllowUsers <USUARIO_ADMIN> garante que mesmo que outro usuário seja criado indevidamente, ele não consegue fazer SSH. LogLevel VERBOSE registra a impressão digital de chave em cada conexão, útil para forense.
Atenção: Teste o login com o novo usuário em uma segunda sessão SSH antes de fechar a sessão atual. Se algo estiver errado, você ainda consegue corrigir.
5. Hardening do Kernel (sysctl)
Arquivo: /etc/sysctl.d/99-hardening.conf
# Anti-spoofing: verifica se o IP de origem faz sentido pela interface
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Desabilita source routing (permite manipular o caminho dos pacotes)
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
# Ignora ICMP redirects (evita ataques de roteamento)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
# Não envia ICMP redirects
net.ipv4.conf.all.send_redirects = 0
# Loga pacotes "marcianos" (IPs impossíveis/suspeitos)
net.ipv4.conf.all.log_martians = 1
# Proteção contra SYN flood (ataque de negação de serviço)
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_max_syn_backlog = 4096
# Desabilita IP forward (máquina não é roteador)
net.ipv4.ip_forward = 0
# Ignora ping broadcast (mitigação ataque Smurf)
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Desabilita IPv6 (se não utilizado no ambiente)
net.ipv6.conf.all.disable_ipv6 = 1
# Restringe acesso a ponteiros do kernel e dmesg
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
# Restringe ptrace (evita que processos inspecionem outros)
kernel.yama.ptrace_scope = 1
# Desabilita core dumps de binários SUID
fs.suid_dumpable = 0
# ASLR máximo: randomiza endereços de memória
kernel.randomize_va_space = 2
sysctl -p /etc/sysctl.d/99-hardening.conf # aplica imediatamente
Motivo: Configurações padrão do kernel são permissivas por compatibilidade. Cada parâmetro fecha um vetor específico: rp_filter previne IP spoofing, SYN cookies protegem contra flood, kptr_restrict impede que atacantes usem vazamentos de ponteiros do kernel para exploits locais.
Nota: Se o servidor for um roteador ou usar IPv6, ajuste
ip_forwardedisable_ipv6de acordo.
6. fail2ban
Arquivo: /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600 # bane por 1 hora
findtime = 600 # janela de 10 minutos para contar tentativas
maxretry = 3 # 3 falhas = banido
[sshd]
enabled = true
port = ssh
maxretry = 3
bantime = 86400 # SSH: bane por 24 horas
systemctl enable fail2ban
systemctl restart fail2ban
Motivo: Bots fazem brute force SSH 24/7. O fail2ban monitora os logs e bane automaticamente IPs que excedem as tentativas. O bantime de 24h para SSH é mais agressivo que o padrão (1h) porque ataques SSH são persistentes e os IPs usados não são reutilizados rapidamente.
7. Desabilitação de Serviços Desnecessários
systemctl disable --now ModemManager # gerenciador de modem (sem uso em servidor)
systemctl disable --now fwupd # atualizações de firmware (interface desktop)
systemctl disable --now snapd # sistema de pacotes snap (desnecessário)
systemctl disable --now udisks2 # montagem de discos (desnecessário)
Motivo: Cada serviço rodando é uma superfície de ataque potencial. Serviços de desktop como ModemManager e udisks2 não têm função em um servidor Linux headless. Menos código rodando = menos vulnerabilidades expostas.
Dica: Use
systemctl list-units --type=service --state=runningpara auditar todos os serviços ativos e desabilitar outros que não sejam necessários ao ambiente.
8. VPN WireGuard com Killswitch
Geração de chaves
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
chmod 600 /etc/wireguard/private.key
cat /etc/wireguard/public.key # registre esta chave no painel do provedor VPN
Arquivo de configuração
/etc/wireguard/wg0.conf (permissão 600):
[Interface]
Address = <IP_TUNEL_VPN>/<PREFIXO>
PrivateKey = <conteúdo de /etc/wireguard/private.key>
DNS = <DNS_PRIMARIO>, <DNS_SECUNDARIO>
# ── Killswitch ──────────────────────────────────────────────────────────
# Regra 1: respostas de conexões ENTRANTES (ex: SSH) saem pelo eth0
PostUp = ip rule add from <IP_DO_SERVIDOR> table main priority 100
# Regra 2: bloqueia qualquer tráfego de saída que não seja:
# - pelo tunnel wg0
# - pacotes marcados pelo WireGuard (os próprios pacotes UDP cifrados)
# - respostas ESTABLISHED/RELATED (replies de conexões recebidas)
# - endereços LOCAL (loopback)
PostUp = iptables -I OUTPUT ! -o %i \
-m mark ! --mark $(wg show %i fwmark) \
-m conntrack ! --ctstate ESTABLISHED,RELATED \
-m addrtype ! --dst-type LOCAL \
-j REJECT
PreDown = ip rule del from <IP_DO_SERVIDOR> table main priority 100
PreDown = iptables -D OUTPUT ! -o %i \
-m mark ! --mark $(wg show %i fwmark) \
-m conntrack ! --ctstate ESTABLISHED,RELATED \
-m addrtype ! --dst-type LOCAL \
-j REJECT
[Peer]
PublicKey = <CHAVE_PUBLICA_PEER_VPN>
AllowedIPs = 0.0.0.0/0
Endpoint = <ENDPOINT_VPN>
PersistentKeepalive = 25
Ativar no boot
systemctl enable wg-quick@wg0
wg-quick up wg0
Como funciona o killswitch:
- VPN UP: todo tráfego novo vai pelo
wg0(tunnel). A regraip rule from <IP_DO_SERVIDOR> table maingarante que respostas SSH saiam peloeth0(não pelo tunnel), mantendo acesso ao servidor. - VPN cai: o
wg0permanece up mas não encaminha pacotes. A regra iptablesREJECTbloqueia qualquer tentativa de sair peloeth0. Nenhum dado vaza para fora da VPN. PersistentKeepalive = 25: mantém o tunnel ativo através de NATs e firewalls.
Verificação pós-ativação
wg show # status do tunnel (handshake, bytes transferidos)
curl https://api.ipify.org # deve retornar o IP do provedor VPN, não o IP real do servidor
Resumo do Estado Final (preencher após execução)
| Item | Antes | Depois |
|---|---|---|
| Firewall | Inativo | UFW ativo, deny all |
| Login root SSH | Permitido | Bloqueado |
| Autenticação SSH | Senha + chave | Chave apenas |
| fail2ban | Não instalado | Ativo |
| Serviços rodando | (contar antes) | (contar depois) |
| IP externo | <IP_DO_SERVIDOR> |
IP do provedor VPN |
| Killswitch VPN | N/A | Ativo via iptables |
| Kernel hardening | Padrão permissivo | sysctl endurecido |
Comandos de Manutenção
# Status da VPN
wg show
systemctl status wg-quick@wg0
# Reiniciar VPN
wg-quick down wg0 && wg-quick up wg0
# Status do firewall
ufw status verbose
# IPs banidos pelo fail2ban
fail2ban-client status sshd
# Logs SSH (últimas 50 linhas)
journalctl -u ssh -n 50 --no-pager
# Conectar ao servidor (do seu laptop)
ssh <USUARIO_ADMIN>@<IP_DO_SERVIDOR>
# Auditar serviços rodando
systemctl list-units --type=service --state=running