Analisador de Logs de Firewall com Python: Detecção de Intrusão Local Que Realmente Funciona
Você Não Precisa de um SOC de R$50 mil Para Saber Quem Bate na Sua Porta
Deixa eu te contar uma coisa que eu demorei pra aprender: o firewall já sabe tudo. Ele registra cada tentativa de conexão, cada scan de porta, cada IP suspeito batendo na sua rede como um vendedor de porta em porta às 3 da manhã. O problema é que ele guarda isso em arquivos de log que ninguém lê — até o disco encher ou algo pior acontecer.
Esse post é sobre construir um analisador de logs de firewall com Python que roda local, custa zero reais e te alerta antes que o atacante perceba que a porta 22 tá aberta. Sem SaaS, sem assinatura mensal, sem depender de terceiro. Só você, seu servidor e um script que faz o trabalho pesado.
Se você já se perguntou “será que alguém tá tentando entrar na minha rede agora?”, a resposta tá no seu log. Vamos ler ele juntos.
O Que um Firewall Realmente Registra
Antes de escrever uma linha de código, você precisa entender o que está olhando. Firewalls como ufw, iptables e nftables geram logs em formatos diferentes, mas todos contêm as mesmas informações essenciais:
- Timestamp: quando o evento aconteceu
- IP de origem: de onde a conexão veio
- IP de destino: para onde tentaram ir
- Porta: qual serviço foi alvo
- Protocolo: TCP, UDP, ICMP
- Ação: ACCEPT, DROP, REJECT
No Ubuntu com UFW ativado, os logs ficam em /var/log/ufw.log. Cada linha parece um absurdo ilegível:
Jun 9 03:14:22 server kernel: [UFW BLOCK] IN=eth0 OUT= MAC=00:11:22:33:44:55 SRC=185.220.101.42 DST=10.0.0.5 LEN=40 TOS=0x00 PREC=0x00 TTL=244 ID=54321 PROTO=TCP SPT=44831 DPT=22 WINDOW=1024 RES=0x00 SYN URGP=0
Traduzindo: às 3:14 da manhã, o IP 185.220.101.42 tentou conectar na porta 22 (SSH) do seu servidor. O UFW bloqueou. Bom para ele. Mas você sabia disso? Provavelmente não — porque ninguém fica olhando log de firewall às 3 da manhã.
Por Que Ferramentas Comerciais São Exagero (e Caro Demais)
Antes de eu escrever esse analisador, eu testei o caminho “profissional”:
- Snort + Barnyard2: poderoso, mas configura em 47 passos e cada atualização de regra quebra algo
- Wazuh: excelente, mas consome 2GB de RAM só pra existir
- Splunk Free: limitado a 500MB/dia — seu firewall gera isso em 3 horas
O Perrengue: Na minha primeira tentativa, eu tentei parsear logs do iptables com regex genérica. Funcionou por 2 horas — até o kernel atualizar e mudar o formato do timestamp. Meu parser engasgou, perdeu 6 horas de logs e eu só percebi quando um IP da China fez 4.000 tentativas de SSH seguidas sem eu notar. Lição: nunca confie em regex frágil para logs do kernel. Use parse posicional baseado em prefixos fixos.
A verdade? Para 90% dos cenários — servidor caseiro, VPS pequeno, rede de escritório com 20 máquinas — você precisa de três coisas: agregação por IP, detecção de padrões repetitivos e alerta quando o volume passa do normal. E isso cabe em 200 linhas de Python.
Arquitetura do Analisador: Simples de Propósito, Robusto de Execução
O design é intencionalmente simples. Quatro componentes:
- Parser: lê o log linha a linha e extrai campos estruturados
- Agregador: conta conexões por IP, porta e faixa de tempo
- Detector: aplica regras de detecção (port scan, brute force, DDoS leve)
- Notifier: envia alerta via webhook, email ou Telegram
# firewall_analyzer.py — estrutura base
import re
import json
from collections import defaultdict, Counter
from datetime import datetime, timedelta
from pathlib import Path
class FirewallLogParser:
"""Parser resiliente para logs UFW/iptables."""
PATTERNS = {
"timestamp": re.compile(r"^(\\w+\\s+\\d+\\s+\\d+:\\d+:\\d+)"),
"action": re.compile(r"\\[(UFW\\s+\\w+)\\]"),
"src": re.compile(r"SRC=([\\d.]+)"),
"dst": re.compile(r"DST=([\\d.]+)"),
"proto": re.compile(r"PROTO=(\\w+)"),
"spt": re.compile(r"SPT=(\\d+)"),
"dpt": re.compile(r"DPT=(\\d+)"),
}
def parse_line(self, line):
result = {}
for field, pattern in self.PATTERNS.items():
match = pattern.search(line)
if match:
result[field] = match.group(1)
elif field in ("src", "dst", "proto"):
return None
return result
def parse_file(self, path):
records = []
for line in Path(path).read_text().splitlines():
parsed = self.parse_line(line)
if parsed:
records.append(parsed)
return records
Repare que o parser não tenta ser esperto com o timestamp completo — ele só extrai o que precisa e descarta linhas malformadas sem quebrar. Isso é intencional: logs do kernel são sujos por natureza. Seu parser precisa ser resiliente, não perfeito.
Detecção de Ameaças: Regras Que Funcionam na Prática
Aqui é onde o script deixa de ser um leitor de log e vira um sistema de detecção. Cada regra foi extraída de incidentes reais:
class ThreatDetector:
"""Regras de detecção baseadas em comportamento."""
def __init__(self):
self.windows = {
"brute_force": {"threshold": 10, "window_min": 5, "port": 22},
"port_scan": {"threshold": 15, "window_min": 2, "unique_ports": True},
"ddos_light": {"threshold": 100, "window_min": 1, "any_port": True},
}
def detect_brute_force(self, records, window_min=5):
"""Detecta tentativas repetidas de SSH em janela curta."""
alerts = []
by_ip = defaultdict(list)
for r in records:
if r.get("dpt") == "22" and r.get("action", "").startswith("UFW BLOCK"):
by_ip[r["src"]].append(r["timestamp"])
for ip, timestamps in by_ip.items():
if len(timestamps) >= self.windows["brute_force"]["threshold"]:
alerts.append({
"type": "BRUTE_FORCE_SSH",
"ip": ip,
"attempts": len(timestamps),
"severity": "HIGH"
})
return alerts
def detect_port_scan(self, records):
"""Detecta varredura de portas."""
alerts = []
by_ip = defaultdict(set)
for r in records:
if r.get("action", "").startswith("UFW BLOCK"):
by_ip[r["src"]].add(r.get("dpt", "0"))
for ip, ports in by_ip.items():
if len(ports) >= self.windows["port_scan"]["threshold"]:
alerts.append({
"type": "PORT_SCAN",
"ip": ip,
"ports_scanned": len(ports),
"severity": "MEDIUM"
})
return alerts
Inteligência de IPs: GeoIP Sem API Paga
Um IP é só um número até você saber de onde ele vem. Para enriquecer seus alertas sem pagar por API:
import subprocess
def resolve_ip_geo(ip):
"""Usa whois local — sem API key, sem rate limit."""
try:
result = subprocess.run(
["whois", ip],
capture_output=True, text=True, timeout=10
)
country = "UNKNOWN"
org = "UNKNOWN"
for line in result.stdout.splitlines():
if line.lower().startswith("country:"):
country = line.split(":", 1)[1].strip()
if line.lower().startswith("org:"):
org = line.split(":", 1)[1].strip()
return {"ip": ip, "country": country, "org": org}
except Exception:
return {"ip": ip, "country": "ERROR", "org": "ERROR"}
Sim, whois é lento. Mas você só roda para IPs que já foram flagged como suspeitos — não para cada entrada do log. Otimização básica: agregue primeiro, enriqueça depois.
Alertas Que Você Realmente Vai Ler
Alerta que ninguém lê é pior que nenhum alerta. O padrão que funcionou pra mim é o resumo em 3 níveis:
def format_alert(alert):
"""Formata alerta para Telegram com hierarquia visual."""
severity_emoji = {"HIGH": "\U0001f534", "MEDIUM": "\U0001f7e1", "LOW": "\U0001f7e2"}
emoji = severity_emoji.get(alert["severity"], "\u26aa")
lines = [
emoji + " [" + alert["type"] + "] — Severidade: " + alert["severity"],
"\U0001f310 IP: " + alert["ip"],
]
if alert.get("country"):
lines.append("\U0001f4cd País: " + alert["country"])
if alert.get("attempts"):
lines.append("\U0001f522 Tentativas: " + str(alert["attempts"]))
if alert.get("ports_scanned"):
lines.append("\U0001f513 Portas varridas: " + str(alert["ports_scanned"]))
lines.append("")
lines.append("\u23f0 " + datetime.now().strftime("%d/%m/%Y %H:%M"))
return "\n".join(lines)
Um alerta no Telegram assim:
🔴 [BRUTE_FORCE_SSH] — Severidade: HIGH
🌐 IP: 185.220.101.42
📍 País: DE
🔢 Tentativas: 47
⏰ 09/06/2026 03:14
Isso eu leio em 2 segundos. E já sei exatamente o que fazer: ufw deny from 185.220.101.42.
Agendamento: Rodando Sem Intervenção
Coloque o script no cron. Simples assim. Para análise a cada 5 minutos:
# /etc/cron.d/firewall-analyzer
*/5 * * * * root /usr/bin/python3 /opt/firewall-analyzer/run.py --since 5m --alert-webhook "https://seu-webhook"
O segredo é o parâmetro --since 5m: o script só analisa as últimas 5 minutos de log. Isso mantém o processamento leve e evita alertas duplicados.
Resultados Reais: O Que Acontece Depois de 30 Dias
Depois de rodar esse analisador por um mês no meu servidor, o resumo foi:
- 12.847 entradas de log processadas
- 34 IPs únicos flagged como suspeitos
- 3 ataques de brute force SSH detectados (todos de IPs diferentes)
- 2 port scans identificados — um da Russia, outro de um IP residencial brasileiro comprometido
- 0 intrusões bem-sucedidas
O mais interessante? 80% dos IPs suspeitos eram conhecidos em blacklists públicas. Isso significa que com um bloqueio de IP básico, eu teria evitado a maioria. Mas sem o analisador, eu nunca saberia que eles estavam batendo na minha porta.
Automatizando a Resposta: Fail2ban + Seu Script
O analisador detecta. O fail2ban bloqueia. Juntos, eles formam um ciclo completo:
import subprocess
def auto_block_ip(ip, reason):
"""Bloqueia IP via UFW e registra a ação."""
try:
subprocess.run(
["ufw", "insert", "1", "deny", "from", ip],
capture_output=True, timeout=10
)
print("\u2705 " + ip + " bloqueado — motivo: " + reason)
with open("/var/log/firewall-analyzer-blocks.log", "a") as f:
f.write(datetime.now().isoformat() + " | BLOCK | " + ip + " | " + reason + "\n")
except Exception as e:
print("\u274c Falha ao bloquear " + ip + ": " + str(e))
Cuidado aqui: auto-bloqueio é poderoso e perigoso. Um falso positivo pode trancar você fora do seu próprio servidor. Sempre mantenha uma whitelist e um acesso de emergência.
O Código Completo (Repositório)
O script completo está estruturado para ser instalado em 3 comandos:
# Instalação
git clone https://github.com/seu-user/firewall-analyzer.git
cd firewall-analyzer
pip install -r requirements.txt
# Teste rápido
python3 run.py --file /var/log/ufw.log --dry-run
# Produção
python3 run.py --since 5m --alert-telegram "SEU_BOT_TOKEN" --auto-block
Dependencies? Quase zero: requests para webhooks, o resto é stdlib. O script roda em Python 3.10+, consome ~30MB de RAM e processa 10.000 linhas de log em menos de 2 segundos.
Por Que Isso Importa
A gente fala muito de “segurança” como se fosse um produto que você compra. Um firewall enterprise, um SIEM, um SOAR. Mas no fim do dia, segurança é visibilidade. Se você não sabe o que tá acontecendo na sua rede, nenhuma ferramenta do mundo vai te proteger.
Esse analisador não vai parar um ataque de estado-nação. Mas vai te mostrar que tem um script kiddie russo tentando adivinhar sua senha SSH às 3 da manhã — e isso, pra maioria de nós, já é o suficiente.
O melhor de tudo? Custa zero. Roda local. E você sabe exatamente o que ele faz porque você pode ler o código. Sem caixa preta, sem telemetria escondida, sem “trust us”.
Qual Automação de Segurança Você Quer Ver Depois?
Eu tenho uma lista de automações que já construí e que fazem diferença no dia a dia:
- Scanner de vulnerabilidades automatizado com nikto + relatório semanal
- Honeypot caseiro com cowrie para capturar ataques e estudar padrões
- Certificado SSL auto-renovável com hook de alerta pré-expiração
- Backup criptografado off-site com verificação de integridade automática
Me conta nos comentários: qual dessas você quer ver com tutorial completo, passo a passo, código pronto? Ou manda outra — a que resolve aquele problema de segurança que te tira o sono.
Porque no fim, o melhor firewall é aquele que você entende. E o melhor analista de segurança é o que não precisa pagar mensalidade pra dormir tranquilo. 🛡️
