Configurar fail2ban com acionamento por webhooks e Telegram no Ubuntu 22.04
Redes & Segurança · Por Kevin Marcondes · Publicado em · 8 min de leitura
Neste tutorial, você vai configurar fail2ban com acionamento por webhooks e alertas no Telegram no Ubuntu 22.04. Vamos criar um script de notificação, registrar uma action personalizada e aplicar tudo em uma jail do SSHD. O objetivo é bloquear tentativas de força bruta e avisar você em tempo real, de forma simples e reproduzível.
Pré-requisitos, objetivos e instalação do fail2ban
Você precisa de um Ubuntu 22.04 com acesso root e saída HTTP/HTTPS. Tenha um bot do Telegram (token e chat ID) e, opcionalmente, um endpoint de webhook. Cuidado: regras incorretas podem bloquear seu IP. Teste de outro host ou use ignoreip.
Objetivos: instalar o fail2ban, criar um script de notificação (webhook + Telegram), registrar uma action e aplicar em uma jail do SSHD.
Se ainda não tem firewall básico, confira como configurar firewall no Ubuntu com UFW. Para um hardening mais amplo, veja o checklist de segurança para VPS Linux.
- Acesso root ou sudo sem senha
- curl instalado para chamadas HTTP
- Bot do Telegram (token) e chat ID
- Opcional: URL de webhook e segredo (HMAC)
# Atualize pacotes, instale e habilite
sudo apt update && sudo apt install -y fail2ban curl
sudo systemctl enable --now fail2ban
# Verifique versão, status e logs
fail2ban-client -V || true
sudo systemctl status fail2ban --no-pager
sudo tail -n 50 /var/log/fail2ban.log || true
Visão geral do fluxo (o que dispara o quê)
O fail2ban lê logs. Quando um padrão de falha ultrapassa o limite, aplica o ban (ex.: iptables) e executa uma action. Criaremos uma action que chama um script. O script envia um POST para seu webhook e alerta no Telegram.
Você pode adaptar o fluxo para Nginx, Postfix e outros serviços. Para reduzir ataques SSH, avalie um bastion: como configurar bastion SSH no Ubuntu 22.04.
| Etapa | Componente | Exemplo |
|---|---|---|
| Evento de falha | Log (sshd) | Múltiplas senhas erradas |
| Detecção | Filtro + jail (fail2ban) | maxretry atingido |
| Bloqueio | Ação de ban (iptables) | DROP no IP ofensivo |
| Notificação | Action personalizada | Script chama webhook e Telegram |
Telegram: criar bot e salvar variáveis com segurança
Crie um bot no Telegram (via BotFather) e obtenha o token. Encontre seu chat ID após enviar /start para o bot. Guardaremos tudo em um arquivo somente‑leitura para root.
Também permitiremos configurar um webhook opcional e um segredo HMAC. Mantenha o arquivo com permissão 600.
- TELEGRAM_BOT_TOKEN: token do bot
- TELEGRAM_CHAT_ID: ID do chat/grupo/canal
- WEBHOOK_URL: URL de automação (opcional)
- WEBHOOK_SECRET: chave para assinar payload (opcional)
# Crie o arquivo de variáveis sensíveis
sudo tee /etc/fail2ban/telegram.env >/dev/null <<'EOF'
TELEGRAM_BOT_TOKEN="coloque_o_token_aqui"
TELEGRAM_CHAT_ID="coloque_o_chat_id_aqui"
# Opcional: envie também para um webhook de automação
WEBHOOK_URL=""
WEBHOOK_SECRET=""
EOF
# Restrinja permissões
sudo chown root:root /etc/fail2ban/telegram.env
sudo chmod 600 /etc/fail2ban/telegram.env
Script de notificação: webhook + Telegram
O script recebe dados do fail2ban (IP, jail e evento), monta um JSON e envia: 1) um POST ao seu webhook, com assinatura HMAC opcional; 2) uma mensagem ao Telegram. Teste manualmente antes de integrar.
A mensagem ao Telegram é texto simples. Para automações, integre o webhook em n8n, Zapier ou Make.
- Assinatura HMAC-SHA256 opcional no header X-Signature
- Payload JSON claro: ip, jail, evento, timestamps
- Saídas independentes: webhook e Telegram
sudo tee /usr/local/bin/f2b_notify.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
ENV_FILE="/etc/fail2ban/telegram.env"
[[ -f "$ENV_FILE" ]] && source "$ENV_FILE"
IP="${1:-}"
JAIL="${2:-}"
LOGPATH="${3:-}"
EVENT="${4:-ban}"
FAILURES="${5:-}"
FINDTIME="${6:-}"
BANTIME="${7:-}"
TS="$(date -Iseconds)"
HOSTNAME="$(hostname -f 2>/dev/null || hostname)"
# Monta payload JSON mínimo
PAYLOAD=$(cat <<JSON
{
"host": "${HOSTNAME}",
"jail": "${JAIL}",
"ip": "${IP}",
"event": "${EVENT}",
"failures": "${FAILURES}",
"findtime": "${FINDTIME}",
"bantime": "${BANTIME}",
"logpath": "${LOGPATH}",
"timestamp": "${TS}"
}
JSON
)
# 1) Envio para webhook (opcional)
if [[ -n "${WEBHOOK_URL:-}" ]]; then
SIG=""
if [[ -n "${WEBHOOK_SECRET:-}" ]]; then
SIG=$(printf '%s' "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -binary | base64)
fi
curl -fsS -X POST "$WEBHOOK_URL" \
-H 'Content-Type: application/json' \
${SIG:+-H "X-Signature: ${SIG}"} \
--data-raw "$PAYLOAD" || true
fi
# 2) Envio para Telegram (opcional)
if [[ -n "${TELEGRAM_BOT_TOKEN:-}" && -n "${TELEGRAM_CHAT_ID:-}" ]]; then
TEXT="[fail2ban] ${EVENT^^} em ${JAIL} — IP ${IP} — host ${HOSTNAME} — ${TS}"
curl -fsS -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-H 'Content-Type: application/json' \
-d "{\"chat_id\":\"${TELEGRAM_CHAT_ID}\",\"text\":\"${TEXT}\"}" || true
fi
EOF
sudo chmod +x /usr/local/bin/f2b_notify.sh
Registrar a action personalizada no fail2ban
Crie uma action em action.d para que a jail possa chamá-la em cada ban e unban. Passaremos ao script as variáveis necessárias.
Manteremos actionban e actionunban. O ban real (iptables) ficará definido na jail.
# /etc/fail2ban/action.d/f2b-notify-webhook-telegram.conf
[Definition]
actionstart =
actionstop =
# Evento de ban
actionban = /usr/local/bin/f2b_notify.sh "<ip>" "<name>" "<logpath>" "ban" "<failures>" "<findtime>" "<bantime>"
# Evento de unban (informativo)
actionunban = /usr/local/bin/f2b_notify.sh "<ip>" "<name>" "<logpath>" "unban" "0" "0" "0"
[Init]
name = default
Jail do SSHD usando iptables e a nova action
Agora criaremos uma jail para sshd. Ela bloqueia via iptables e dispara nossa action de notificação. Adicione seu IP em ignoreip para não se banir.
Adapte maxretry, findtime e bantime ao seu risco e volume de acessos.
- backend systemd funciona bem no Ubuntu 22.04
- iptables-nft é padrão; iptables-multiport segue válido
- ignoreip aceita listas e CIDRs
# /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
port = 22
logpath = %(sshd_log)s
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 192.168.0.0/16
# Ação de bloqueio (iptables)
banaction = iptables-multiport
# Notificações
action = f2b-notify-webhook-telegram
Testes: recarregar, simular falhas e validar alertas
Hora de testar. Recarregue o fail2ban, verifique a jail sshd e simule logins com senha errada a partir de outro host. Confirme o ban, a execução da action e o recebimento dos alertas no Telegram e no webhook.
Você também pode forçar um unban para validar o alerta de desbloqueio.
- Use uma máquina separada para testar falhas de SSH
- Monitore /var/log/fail2ban.log em tempo real
- Se nada chegar ao Telegram, valide token e chat ID
# Recarregar e inspecionar
sudo fail2ban-client reload
sudo fail2ban-client status
sudo fail2ban-client status sshd
# Acompanhar logs
sudo tail -f /var/log/fail2ban.log &
# (Em outro host) force tentativas erradas de SSH
# ssh usuario@SEU_IP # digite senhas erradas
# Checar IPs banidos e desbanir para testar unban
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 1.2.3.4 # troque pelo IP de teste
Solução de problemas e aprimoramentos úteis
Alguns problemas são comuns e fáceis de resolver. Veja dicas e extensões do setup abaixo. Para observabilidade, considere métricas com Prometheus e dashboards com Grafana: veja o guia em configurar Prometheus e Grafana com Docker Compose em VPS.
- Sem alertas: verifique permissões 600 em /etc/fail2ban/telegram.env e se o script é executável.
- Proxy corporativo: exporte http_proxy/https_proxy para o serviço.
- UFW ativo: iptables-multiport costuma coexistir; se conflitar, use ufw como banaction.
- Mensagem do Telegram com caracteres estranhos: simplifique o TEXT.
- Webhook não recebe: teste manual com curl e valide retorno HTTP 2xx.
- Reduza ruído: ajuste filtros, maxretry e findtime; considere banaction incremental.
- Assinatura: valide X-Signature no seu fluxo (n8n, Zapier, Make).
# Teste manual do webhook (substitua URL)
WEBHOOK_URL="https://example.com/webhook"
payload='{"hello":"world"}'
curl -v -X POST "$WEBHOOK_URL" -H 'Content-Type: application/json' --data-raw "$payload"
Perguntas frequentes
Funciona com outros serviços além do SSH (sshd)?
Sim. Crie ou habilite jails para Nginx, Postfix e Apache, apontando o log certo e ajustando maxretry, findtime e bantime. Reuse a mesma action para padronizar os alertas.
Como encontro meu chat ID no Telegram?
Inicie conversa com seu bot, envie uma mensagem e use um bot utilitário para obter o chat ID. Também é possível ler o update JSON da API do Telegram após enviar a primeira mensagem.
UFW e fail2ban podem rodar juntos?
Geralmente, sim. O fail2ban aplica regras temporárias enquanto o UFW mantém a política base. Se houver conflito, troque a ação de ban para ufw no lugar de iptables-multiport.
Como evitar me banir por engano?
Use ignoreip com seu IP fixo ou um bloco confiável. Teste de outra máquina e, se necessário, reduza temporariamente o bantime. Se travar o acesso, use o console e execute unbanip.
Posso assinar o payload do webhook para validar a origem?
Sim. Defina WEBHOOK_SECRET. O script calcula um HMAC-SHA256 do corpo e envia no header X-Signature em base64. No receptor, recalcule e compare para validar.
Como integrar com n8n, Zapier ou Make?
Aponte WEBHOOK_URL para um webhook público criado na ferramenta. A automação pode rotear alertas para e-mail, SMS, Slack e abrir tickets. Valide X-Signature antes de processar.
Precisa adaptar este setup ao seu ambiente?
Quer ampliar para outras jails, reduzir falsos positivos e padronizar alertas? Vamos revisar filtros, actions e automações do seu stack.
Falar sobre segurança e automaçãoVeja também
- tutorial: implementar Canary releases com Traefik em Docker Compose usando headers e weight routing para deploys graduais de aplicações PHP
- Tutorial: configurar HAProxy com Let's Encrypt e healthchecks para balanceamento de tráfego entre containers Docker em VPS (passo a passo)
- Tutorial prático: implementar mTLS entre Nginx e microserviços usando smallstep CA em Docker Compose
- Tutorial: configurar cgroup v2 e systemd ResourceControl para limitar CPU, memória e I/O de containers Docker no Debian