Fail2ban na VPS: bloquear ataques de força bruta

Fail2ban monitora logs do sistema e bane automaticamente IPs que excedem um número de tentativas falhas num intervalo de tempo. É a proteção mais eficaz contra ataques de força bruta ao SSH, bots que tentam milhares de senhas são bloqueados após 5 tentativas e ficam banidos por horas ou dias.

Instalar e habilitar o Fail2ban

Fail2ban está nos repositórios padrão do Ubuntu/Debian. Após instalar, o jail SSH já vem habilitado por padrão:

bash
# Instalar
sudo apt update && sudo apt install -y fail2ban

# Habilitar e iniciar
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

# Ver status (deve mostrar jail sshd ativo)
sudo fail2ban-client status
sudo fail2ban-client status sshd

# Ver IPs atualmente banidos
sudo fail2ban-client status sshd | grep "Banned IP"

Configuração personalizada (jail.local)

Nunca edite jail.conf, crie jail.local que sobrescreve as configurações padrão e sobrevive a atualizações do pacote:

ini
# Criar arquivo de configuração local
sudo nano /etc/fail2ban/jail.local

# Conteúdo recomendado para VPS de produção:
[DEFAULT]
# Ignorar seu IP fixo (nunca seja banido acidentalmente)
ignoreip = 127.0.0.1/8 ::1 SEU_IP_FIXO

# Tempo de ban: 1 hora (3600s) ou 24h (86400)
bantime = 3600

# Janela de observação: 10 minutos
findtime = 600

# Máximo de tentativas antes do ban
maxretry = 5

# Backend de detecção (systemd para Ubuntu 22.04+)
backend = systemd

[sshd]
enabled = true
port = ssh
filter = sshd
maxretry = 3       # SSH: threshold mais baixo
bantime = 86400    # ban de 24h para SSH

Proteger o Nginx (WordPress, apps web)

Além do SSH, configure jails para o Nginx para bloquear ataques ao painel de login do WordPress, tentativas de exploração de URL e scanners:

ini
# Adicionar ao /etc/fail2ban/jail.local:

[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
bantime = 3600

[nginx-limit-req]
enabled = true
port = http,https
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 10
bantime = 600

# Para WordPress — criar filtro customizado:
# /etc/fail2ban/filter.d/wordpress.conf
[Definition]
failregex = ^<HOST> .* "POST /wp-login.php
ignoreregex =

# Jail para WordPress:
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 86400

Gerenciar bans: verificar, desbanir e testar

Comandos do dia a dia para gerenciar o Fail2ban:

bash
# Ver todos os jails ativos e IPs banidos
sudo fail2ban-client status
sudo fail2ban-client status sshd

# Desbanir um IP específico (ex: se você mesmo foi banido)
sudo fail2ban-client set sshd unbanip SEU_IP

# Banir manualmente um IP suspeito
sudo fail2ban-client set sshd banip 203.0.113.0

# Ver log do Fail2ban em tempo real
sudo tail -f /var/log/fail2ban.log

# Testar se um filtro detecta corretamente (sem banir)
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

# Recarregar configuração após editar jail.local
sudo fail2ban-client reload

Ban persistente e recidivismo

Configure ban crescente para IPs que continuam atacando após desban:

ini
# Adicionar ao /etc/fail2ban/jail.local:

[DEFAULT]
# Ban progressivo: 1h → 1 dia → 1 semana
# Requer Fail2ban 0.11+ (Ubuntu 22.04 inclui)
bantime.increment = true
bantime.rndtime = 600     # variação aleatória para evitar timing attacks
bantime.maxtime = 604800  # máximo 1 semana (604800 segundos)
bantime.factor = 24       # multiplica o bantime a cada reincidência

# Recalcular ban:
# 1ª infração: 1h × 1 = 1h
# 2ª infração: 1h × 24 = 24h
# 3ª infração: 1h × 24² = 576h (~24 dias, limitado a 1 semana)

Não quer configurar manualmente?

Implante o VPS em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Use os dois em conjunto. ufw limit SSH bloqueia conexões que ultrapassam 6/30s de forma estática. Fail2ban analisa o conteúdo dos logs (tentativas de autenticação falhadas) e bane por tempo configurável. Fail2ban é mais inteligente e flexível; UFW rate limiting é uma primeira camada simples.

Acesse o console VNC da Runstack (painel → VPS → Console), o console funciona independente de rede. No console: sudo fail2ban-client set sshd unbanip SEU_IP. Para evitar no futuro, adicione seu IP à lista ignoreip no jail.local.

Mínimo. O Fail2ban é um processo Python leve que fica em polling nos logs. Em VPS muito atacadas (milhares de tentativas/minuto), o overhead pode ser perceptível, nesse caso, considere blocklists de IPs ao nível de provedor (como o painel de firewall da Runstack) como primeira linha de defesa.

O desafio é que logs de containers não ficam em /var/log por padrão. Soluções: (1) montar volumes de log do Nginx no host e apontar logpath para o diretório do host; (2) usar driver de log json-file e processar com fail2ban; (3) usar Crowdsec (alternativa moderna ao Fail2ban com inteligência coletiva).

Para SSH: 24h (86400s) com maxretry 3. Para apps web: 1h (3600s) com maxretry 5–10. Com bantime.increment ativo, reincidentes ficam banidos cada vez por mais tempo. IPs de botnets conhecidas podem ser banidos permanentemente com bantime = -1.