Fail2ban: proteger SSH e Nginx contra brute force

    Um VPS com SSH na porta 22 recebe centenas de tentativas de login por dia de bots automatizados. Fail2ban monitora logs em tempo real e bane automaticamente IPs que excedem o limite de tentativas — reduzindo a superfície de ataque sem exigir intervenção manual.

    Instalação e configuração básica

    Instalar e configurar jails padrão para SSH:

    bash
    # Instalar Fail2ban:
    sudo apt update && sudo apt install fail2ban
    
    # IMPORTANTE: nunca editar /etc/fail2ban/jail.conf diretamente
    # Criar arquivo de override que persiste em atualizações:
    sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
    
    # Ou criar arquivo limpo com apenas as configurações desejadas:
    sudo tee /etc/fail2ban/jail.local << 'EOF'
    [DEFAULT]
    # Banir por 1 hora após 5 tentativas em 10 minutos:
    bantime  = 1h
    findtime = 10m
    maxretry = 5
    
    # Nunca banir estes IPs (seu IP de acesso):
    ignoreip = 127.0.0.1/8 ::1 203.0.113.10
    
    # Usar UFW para banir (padrão: iptables):
    banaction = ufw
    
    # Notificação por email:
    # destemail = admin@seudominio.com.br
    # sender    = fail2ban@seudominio.com.br
    # action    = %(action_mwl)s   # banir + email com log
    
    [sshd]
    enabled  = true
    port     = ssh
    logpath  = %(sshd_log)s
    backend  = %(sshd_backend)s
    maxretry = 3           # SSH: limite mais restritivo
    bantime  = 24h         # banir por 24h após 3 tentativas
    EOF
    
    sudo systemctl enable fail2ban
    sudo systemctl start fail2ban

    Jail para Nginx

    Proteger Nginx contra scan de vulnerabilidades e brute force em formulários:

    bash
    # Adicionar ao /etc/fail2ban/jail.local:
    
    # Bloquear scans de bots (404 repetidos, tentativas de exploits):
    [nginx-http-auth]
    enabled  = true
    port     = http,https
    logpath  = /var/log/nginx/error.log
    maxretry = 5
    
    [nginx-botsearch]
    enabled  = true
    port     = http,https
    logpath  = /var/log/nginx/access.log
    maxretry = 2
    bantime  = 1h
    
    # Filtro customizado para login de app Node.js (429 Too Many Requests):
    # /etc/fail2ban/filter.d/nodejs-login.conf:
    sudo tee /etc/fail2ban/filter.d/nodejs-login.conf << 'EOF'
    [Definition]
    failregex = ^<HOST> .* "POST /api/auth/login HTTP.*" (401|429) .*$
    ignoreregex =
    EOF
    
    # Jail para login da API:
    sudo tee -a /etc/fail2ban/jail.local << 'EOF'
    
    [nodejs-login]
    enabled  = true
    port     = http,https
    logpath  = /var/log/nginx/access.log
    filter   = nodejs-login
    maxretry = 10
    findtime = 5m
    bantime  = 2h
    EOF
    
    sudo fail2ban-client reload

    Monitorar e gerenciar bans

    Verificar status, desbanir IPs e consultar estatísticas:

    bash
    # Status geral de todas as jails:
    sudo fail2ban-client status
    
    # Status de jail específica (IPs banidos, estatísticas):
    sudo fail2ban-client status sshd
    # Saída:
    # Status for the jail: sshd
    # |- Filter
    # |  |- Currently failed: 2
    # |  |- Total failed: 847
    # `- Actions
    #    |- Currently banned: 3
    #    |- Total banned: 156
    #    `- Banned IP list: 203.0.113.5 198.51.100.8 192.0.2.1
    
    # Desbanir IP específico:
    sudo fail2ban-client set sshd unbanip 203.0.113.5
    
    # Banir IP manualmente:
    sudo fail2ban-client set sshd banip 203.0.113.99
    
    # Logs do Fail2ban:
    sudo tail -f /var/log/fail2ban.log
    
    # Testar filtro sem aplicar ban (dry run):
    sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
    
    # Verificar se UFW aplicou os bans:
    sudo ufw status numbered | grep DENY

    Banimento progressivo (aumentar penalidade por reincidência)

    Aumentar automaticamente o tempo de ban para IPs reincidentes:

    bash
    # /etc/fail2ban/jail.local — bantime progressivo:
    [DEFAULT]
    # bantime.increment: cada reincidência aumenta o ban exponencialmente
    bantime.increment   = true
    bantime.factor      = 1
    bantime.formula     = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor
    # 1ª vez: 1h, 2ª: 2h, 3ª: 4h, 4ª: 8h... até ~1 ano
    
    # Alternativa simples: ban permanente após N reincidências:
    # Criar ação de ban permanente para IPs que voltam muitas vezes:
    # /etc/fail2ban/action.d/ufw-permanent.conf:
    sudo tee /etc/fail2ban/action.d/ufw-permanent.conf << 'EOF'
    [Definition]
    actionban  = ufw deny from <ip> to any
    actionunban = ufw delete deny from <ip> to any
    EOF
    
    [sshd-permanent]
    enabled  = true
    port     = ssh
    logpath  = %(sshd_log)s
    maxretry = 10    # 10 tentativas totais ao longo do tempo
    bantime  = -1    # -1 = ban permanente
    action   = ufw-permanent

    Integração com Telegram para alertas em tempo real

    Receber notificação no Telegram quando um IP é banido:

    bash
    # /etc/fail2ban/action.d/telegram-notify.conf:
    sudo tee /etc/fail2ban/action.d/telegram-notify.conf << 'EOF'
    [Definition]
    actionban = curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage   -d chat_id=<CHAT_ID>   -d text="🚫 Fail2ban: IP <ip> banido na jail <name> em $(hostname). Tentativas: <failures>. Log: $(tail -5 <logpath> | tr '
    ' ' ')"
    
    actionunban = curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage   -d chat_id=<CHAT_ID>   -d text="✅ Fail2ban: IP <ip> desbanido da jail <name> em $(hostname)"
    EOF
    
    # Adicionar ao jail.local:
    [DEFAULT]
    action = %(action_)s
             telegram-notify[TOKEN=SEU_BOT_TOKEN, CHAT_ID=SEU_CHAT_ID]
    
    # Testar a notificação:
    sudo fail2ban-client set sshd banip 1.2.3.4
    sudo fail2ban-client set sshd unbanip 1.2.3.4

    $ runstack deploy --plan starter

    Não quer configurar manualmente?

    Não quer configurar manualmente? Implante o VPS Linux em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.

    Perguntas frequentes