hardening-linux-servers/101-Hardening-Linux-Servers.MD

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 iptables
  • fail2ban: bane IPs após tentativas de força bruta
  • unattended-upgrades: atualizações de segurança automáticas
  • wireguard/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_forward e disable_ipv6 de 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=running para 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 regra ip rule from <IP_DO_SERVIDOR> table main garante que respostas SSH saiam pelo eth0 (não pelo tunnel), mantendo acesso ao servidor.
  • VPN cai: o wg0 permanece up mas não encaminha pacotes. A regra iptables REJECT bloqueia qualquer tentativa de sair pelo eth0. 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