Dia 21: Segurança de Rede — IDS/IPS, Suricata e Zeek

Curso de Redes em 30 Dias — Dia 21 de 30. No Dia 20 falámos de monitorização com SNMP, Zabbix e PRTG; hoje subimos o nível para segurança activa. Um firewall bloqueia tráfego por regras, mas não detecta intrusões que passam por portas legítimas. IDS (Intrusion Detection System) e IPS (Intrusion Prevention System) vão mais além: analisam o conteúdo dos pacotes à procura de padrões maliciosos. Este artigo cobre as duas ferramentas open-source mais usadas em PME: Suricata (motor IDS/IPS de alta performance) e Zeek (framework de análise de tráfego orientada a scripts). Para cada uma: conceitos, instalação, configuração prática e verificação.

ℹ IDS detecta e alerta; IPS detecta e bloqueia. A diferença crítica está na posição na rede: IDS em modo promíscuo (passivo), IPS inline (activo, pode parar tráfego).

1. IDS vs IPS — Conceitos Fundamentais

Um firewall filtra pacotes por endereço, porta e estado da ligação — é a primeira linha de defesa. Mas um firewall não inspeciona o conteúdo dos pacotes. Um ataque HTTP que passa pela porta 80 legítima não é bloqueado pelo firewall. Aqui entram IDS e IPS: sistemas que analisam o payload dos pacotes à procura de assinaturas conhecidas de ataques, anomalias de protocolo ou comportamentos suspeitos.

Analogia: o firewall é o guarda do portão que verifica a identidade de quem entra. O IDS é a câmara de vigilância que regista tudo e alerta se vir algo suspeito. O IPS é o guarda dentro do edifício que pode parar um intruso a meio da acção.

Característica IDS (Detection) IPS (Prevention)
Posição na rede Modo promíscuo (porta SPAN/mirror) Inline (tráfego passa pelo sensor)
Acção sobre tráfego malicioso Apenas alerta (log + notificação) Bloqueia ou derruba a ligação
Impacto na rede se falhar Nenhum — tráfego continua a fluir Pode parar todo o tráfego (ponto único de falha)
Latência introduzida Zero (não está no caminho) Pequena (análise em tempo real)
Caso de uso típico Auditoria, forense, detecção pós-facto Protecção activa em tempo real

A escolha entre IDS e IPS depende da tolerância a latência e do risco de falsos positivos. Num ambiente de produção onde um falso positivo bloqueia tráfego legítimo, começa-se com IDS (passivo) para afinar as regras e só depois migra-se para IPS (activo). O Suricata suporta ambos os modos com a mesma configuração base — basta mudar a interface de captura (documentação oficial Suricata).

O Zeek (anteriormente Bro) tem uma abordagem diferente: não é um motor de assinaturas como o Suricata, mas sim um framework de análise de tráfego que regista metadados detalhados de todas as ligações. Em vez de procurar padrões conhecidos, o Zeek permite escrever scripts que detectam comportamentos anómalos — por exemplo, ligações DNS para domínios recém-registados, transferências de ficheiros grandes fora de horas, ou scans de portas internas (documentação oficial Zeek).

2. Suricata — Instalação e Configuração Base

O Suricata é um motor IDS/IPS de alta performance desenvolvido pela Open Information Security Foundation (OISF). Suporta inspecção de tráfego em multi-thread, processamento a 10+ Gbps e integração com Emerging Threats para regras actualizadas. É a alternativa open-source mais utilizada em PME e em soluções comerciais como OPNsense (site oficial, GitHub).

Pré-requisitos: um servidor Linux com pelo menos 2 GB de RAM, uma interface de rede com suporte para captura em modo promíscuo (para IDS) ou NFQueue (para IPS), e acesso root.

Requisito Detalhe
Sistema operativo Debian 12+, Ubuntu 22.04+, RHEL 9+, Fedora 39+
RAM mínima 2 GB (4 GB recomendado para IPS em produção)
Dependências libpcap, libnetfilter-queue, libnfnetlink, python3, jq
Permissões root para instalação; utilizador suricata para execução

A instalação varia conforme a distribuição. Em Debian/Ubuntu, o pacote nos repositórios oficiais é funcional mas pode não ser a versão mais recente. Para produção, recomenda-se o PPA oficial Suricata (Debian package, Arch Wiki).

# Ubuntu/Debian — instalar Suricata via PPA oficial
sudo add-apt-repository ppa:oisf/suricata-stable
sudo apt update
sudo apt install suricata jq

# Fedora/RHEL
sudo dnf install suricata jq

# Arch Linux
sudo pacman -S suricata jq

O que cada linha faz:

  • add-apt-repository ppa:oisf/suricata-stable — adiciona o repositório oficial da OISF com a versão estável mais recente
  • jq — processador JSON necessário para ler os alertas do EVE JSON (formato de saída do Suricata)

Após a instalação, verificar a versão e o ficheiro de configuração principal:

# Verificar versao instalada
suricata --build-info | head -5

# Configuracao principal em /etc/suricata/suricata.yaml
# Verificar interface de captura pre-definida
grep -E "interface|af-packet" /etc/suricata/suricata.yaml | head -10

3. Passo 1 — Regras e Assinaturas no Suricata

O Suricata sem regras não detecta nada. As regras (assinaturas) são padrões que descrevem tráfego malicioso — semelhante às assinaturas de um antivírus. Existem três fontes principais: o conjunto Emerging Threats (ET Open, gratuito), o conjunto ET Pro (subscrição) e regras customizadas. A ferramenta suricata-update gere a transferência e actualização automática (documentação de regras, Emerging Threats).

# Actualizar fontes de regras
sudo suricata-update update-sources

# Listar fontes disponiveis
sudo suricata-update list-sources

# Adicionar ET Open (gratuito) — ja vem por defeito
sudo suricata-update enable-source et/open

# Adicionar ET Pro Telemetry (gratuito com registo)
sudo suricata-update enable-source et/telemetry

# Transferir e aplicar regras
sudo suricata-update

# Verificar numero de regras carregadas
sudo suricata-update --list-rules | wc -l

O que cada comando faz:

  • update-sources — actualiza o índice de fontes de regras disponíveis no repositório Suricata
  • enable-source et/open — activa o conjunto Emerging Threats Open (gratuito, ~30 000 regras)
  • suricata-update — transfere as regras, converte formato se necessário, e instala em /var/lib/suricata/rules/

A sintaxe de uma regra Suricata segue o formato padronizado de assinaturas de IDS. Uma regra típica tem cabeçalho (acção, protocolo, endereços, portas) e opções (mensagem, conteúdo, referências):

# Exemplo: detectar tentativa de SQL injection em HTTP
alert http any any -> $HOME_NET any (msg:"SQL Injection Attempt - UNION SELECT"; content:"UNION"; nocase; content:"SELECT"; nocase; distance:within 50; sid:1000001; rev:1; classtype:web-application-attack;)

# Exemplo: detectar scan de portas TCP SYN
alert tcp $EXTERNAL_NET any -> $HOME_NET any (flags:S,12; detection_filter:track by_src, count 30, seconds 10; msg:"TCP Port Scan"; sid:1000002; rev:1; classtype:attempted-recon;)

# Regra personalizada para detectar ficheiros executaveis em HTTP
alert http any any -> $HOME_NET any (msg:"Windows Executable Transfer over HTTP"; file_data; content:"MZ"; byte_test:2,=,0x5a4d,0; sid:1000003; rev:1;)

Explicação dos campos principais:

  • alert — acção: gerar alerta. Outras opções: drop (bloquear em IPS), pass (ignorar), reject (rejeitar com RST)
  • $HOME_NET — variável definida no suricata.yaml que representa a rede interna a proteger
  • content:"UNION" — procura a string “UNION” no payload
  • nocase — case-insensitive (procura “union”, “Union”, “UNION”)
  • sid — Suricata ID, identificador único da regra (1000000+ para regras customizadas)
  • classtype — categoria da regra (web-application-attack, attempted-recon, trojan-activity, etc.)

Atenção: regras com drop em modo IPS bloqueiam tráfego em tempo real. Testar sempre em modo IDS (alert) primeiro para evitar falsos positivos que cortam ligações legítimas.

4. Passo 2 — Suricata em Modo IPS Inline

O modo IDS usa captura passiva (porta SPAN no switch ou modo promíscuo na interface) — não interfere com o tráfego. O modo IPS coloca o Suricata no caminho do tráfego usando NFQueue (Netfilter Queue) no Linux. Isto permite que o Suricata bloqueie pacotes maliciosos antes de chegarem ao destino. A configuração inline requer duas peças: o suricata.yaml e as regras de nftables/iptables que enviam tráfego para a queue (configuração Suricata YAML).

Analogia: no modo IDS, o Suricata é um observador que vê o tráfego passar e toma nota. No modo IPS, é um controlador de fronteira: todo o tráfego tem de passar por ele para ser analisado antes de continuar.

# 1. Editar suricata.yaml para modo NFQ
sudo nano /etc/suricata/suricata.yaml

# Na secao nfq, garantir:
nfq:
  mode: accept
  repeat-mark: 1
  repeat-cnt: 3
  route-queue: -2
  batchcount: 20
  batchsize: 16000

# 2. Regras nftables para enviar tráfego para a queue
# Criar ficheiro /etc/nftables.d/suricata-ips.nft
table inet suricata-ips {
    chain input {
        type filter hook input priority -10; policy accept;
        counter queue num 0 bypass
    }
    chain forward {
        type filter hook forward priority -10; policy accept;
        counter queue num 0 bypass
    }
    chain output {
        type filter hook output priority -10; policy accept;
        counter queue num 0 bypass
    }
}

# 3. Aplicar regras nftables
sudo nft -f /etc/nftables.d/suricata-ips.nft

# 4. Iniciar Suricata em modo NFQ
sudo suricata -c /etc/suricata/suricata.yaml -q 0 -D

# 5. Verificar processo activo
ps aux | grep suricata
sudo journalctl -u suricata -f --no-pager | head -20

O que cada elemento faz:

  • mode: accept — se o Suricata falhar, o tráfego continua a fluir (bypass). A alternativa mode: repeat re-envia pacotes não verificados
  • queue num 0 bypass — envia pacotes para a queue 0; bypass garante que se o Suricata parar, o tráfego não fica bloqueado
  • -q 0 — escuta na NFQueue número 0 (mesma queue das regras nftables)
  • -D — modo daemon (corre em background)

Atenção: o modo IPS inline torna o Suricata um ponto único de falha. Se o processo parar com mode: repeat (sem bypass), todo o tráfego para. Usar sempre bypass nas regras nftables em produção e monitorizar o processo com systemd ou supervisor.

5. Zeek — Instalação e Análise de Tráfego

O Zeek (anteriormente Bro) é um framework de análise de tráfego de rede desenvolvido originalmente no Lawrence Berkeley National Laboratory. Ao contrário do Suricata, que é orientado a assinaturas (procurar padrões conhecidos), o Zeek é orientado a scripts: regista metadados de todas as ligações e permite escrever lógica customizada para detectar comportamentos anómalos. É a ferramenta preferida para análise forense e detecção de ameaças avançadas (site oficial, GitHub).

Analogia: o Suricata é um cão de caça treinado para reconhecer ladrões específicos (assinaturas). O Zeek é uma câmara inteligente que regista tudo o que se passa e permite definir regras personalizadas: “alerta se alguém entrar fora de horas” ou “alerta se houver transferências grandes para o exterior”.

# Ubuntu/Debian — instalar Zeek via repositorio oficial
sudo wget -O /etc/apt/trusted.gpg.d/zeek.gpg https://download.zeek.org/gpg/key
echo "deb [signed-by=/etc/apt/trusted.gpg.d/zeek.gpg] https://download.zeek.org/debian stable main" | sudo tee /etc/apt/sources.list.d/zeek.list
sudo apt update
sudo apt install zeek

# Fedora/RHEL
sudo dnf install zeek

# Arch Linux (via AUR)
yay -S zeek

Após a instalação, adicionar o directório de binários ao PATH e verificar:

# Adicionar ao PATH (Ubuntu/Debian)
export PATH=$PATH:/opt/zeek/bin

# Verificar versao
zeek --version

# Configurar interface de captura em /opt/zeek/etc/node.cfg
# Para modo standalone com captura na interface eth0:
sudo nano /opt/zeek/etc/node.cfg

[zeek-logger]
type=logger
host=localhost

[zeek-manager]
type=manager
host=localhost

[zeek-proxy-1]
type=proxy
host=localhost

[zeek-worker-1]
type=worker
host=localhost
interface=eth0

# Iniciar Zeek em modo cluster
sudo /opt/zeek/bin/zeekctl deploy

# Verificar status
sudo /opt/zeek/bin/zeekctl status

O que cada componente do cluster faz:

  • logger — recebe e escreve os ficheiros de log de todos os workers (centralização)
  • manager — coordena o cluster, mantém estado global, distribui configuração
  • proxy — intermediário de comunicação entre manager e workers (reduz carga no manager)
  • worker — processo que captura e analisa tráfego numa interface; pode haver múltiplos (um por interface ou por CPU core)

6. Passo 3 — Logs Zeek e Detecção de Anomalias

O Zeek gera dezenas de ficheiros de log em formato TSV (tab-separated), cada um cobrindo um aspecto do tráfego. Estes logs ficam em /opt/zeek/logs/current/ durante a execução e são arquivados diariamente em /opt/zeek/logs/YYYY-MM-DD/. A documentação completa de todos os logs está no manual de referência do Zeek.

Ficheiro de Log Conteúdo Caso de Uso
conn.log Todas as ligações (IP origem/destino, porta, duração, bytes) Base para qualquer análise de tráfego
dns.log Queries e respostas DNS Detectar DNS tunneling, C2, domínios suspeitos
http.log Pedidos e respostas HTTP (URL, user-agent, MIME) Detectar downloads maliciosos, C2 HTTP
ssl.log Ligações TLS/SSL (SNI, cipher, certificado) Detectar certificados auto-assinados, JA3 fingerprinting
files.log Ficheiros transferidos via HTTP, FTP, SMB, etc. Detectar transferências de executáveis, exfiltração
weird.log Comportamentos anómalos de protocolo Detectar scans, floods, ataques de protocolo

Para análise prática, o log conn.log é o ponto de partida. Contém todas as ligações de rede com timestamps, IPs, portas, duração e volumes de dados transferidos. Com jq ou zeek-cut podemos extrair padrões:

# Listar logs activos
ls -la /opt/zeek/logs/current/

# Top 10 IPs de origem com mais ligacoes
zeek-cut id.orig_h < /opt/zeek/logs/current/conn.log | sort | uniq -c | sort -rn | head -10

# Ligacoes para portas nao standard (suspeitas de C2)
zeek-cut id.orig_h id.resp_h id.resp_p < /opt/zeek/logs/current/conn.log | awk '$3 < 1024 || $3 > 49151' | sort | uniq -c | sort -rn | head -20

# Queries DNS para dominios com TLD suspeito
zeek-cut query < /opt/zeek/logs/current/dns.log | grep -E '\.(xyz|top|click|loan|work)$' | sort | uniq -c | sort -rn

# Transferencias de ficheiros executaveis via HTTP
zeek-cut id.orig_h id.resp_h mime_type < /opt/zeek/logs/current/http.log | grep -i executable

# Ligacoes SSH para IPs externos
zeek-cut id.orig_h id.resp_h < /opt/zeek/logs/current/ssh.log | sort | uniq -c | sort -rn

O que cada comando faz:

  • zeek-cut id.orig_h — extrai a coluna do IP de origem do conn.log (formato TSV)
  • sort | uniq -c | sort -rn — conta ocorrências por IP e ordena por frequência descendente (top talkers)
  • O filtro awk '$3 < 1024 || $3 > 49151' — destaca ligações para portas fora das gamas standard (0-1023 bem conhecidas, 49152+ efémeras)
  • grep -E '\.(xyz|top|click...)' — procura TLDs frequentemente associados a malware e phishing

O Zeek também suporta scripts personalizados para detecção em tempo real. Um script básico para alertar sobre scans de portas internas:

# Ficheiro: /opt/zeek/share/zeek/site/detect-port-scan.zeek

@load base/protocols/conn

global port_scan_threshold = 20;
global port_scan_window: interval = 60sec;

global port_scans: table[addr] of count = {};

event new_connection(c: connection)
{
    if (c$id$orig_h !in 10.0.0.0/8 && c$id$orig_h !in 192.168.0.0/16)
        return;

    if (c$id$resp_h in 10.0.0.0/8 || c$id$resp_h in 192.168.0.0/16)
    {
        if (c$id$orig_h in port_scans)
            port_scans[c$id$orig_h] += 1;
        else
            port_scans[c$id$orig_h] = 1;

        if (port_scans[c$id$orig_h] == port_scan_threshold)
        {
            print fmt("ALERTA: Possivel scan de portas de %s (%d ligacoes em 60s)",
                c$id$orig_h, port_scans[c$id$orig_h]);
        }
    }
}

event zeek scheduled port_scan_cleanup()
{
    port_scans = {};
}

schedule port_scan_cleanup { port_scan_window };

Este script conta ligações por IP de origem numa janela de 60 segundos. Quando um IP interno excede 20 ligações para outros hosts internos, gera um alerta. Para activar o script, adicioná-lo ao local.zeek:

# Adicionar a /opt/zeek/share/zeek/site/local.zeek
@load detect-port-scan

# Reiniciar Zeek para carregar o script
sudo /opt/zeek/bin/zeekctl restart

# Verificar alertas no log de notificacoes
tail -f /opt/zeek/logs/current/notice.log

7. Suricata vs Zeek — Comparação Prática

Embora ambos analisem tráfego de rede, Suricata e Zeek têm filosofias diferentes e são frequentemente usados em conjunto. O Suricata é um motor de assinaturas optimizado para performance e blocking em tempo real. O Zeek é um framework de análise que regista metadados ricos e permite detecção comportamental customizada. A combinação dos dois é o padrão em Security Operations Centers (SOC) de PME.

Critério Suricata Zeek
Tipo principal IDS/IPS por assinaturas Framework de análise de tráfego
Modo IPS inline Sim (NFQueue) Não (apenas passivo)
Detecção Padrões conhecidos (assinaturas) Comportamentos anómalos (scripts)
Formato de saída EVE JSON (alertas + metadados) TSV (dezenas de logs por protocolo)
Performance 10+ Gbps com multi-thread 1-10 Gbps consoante scripts activos
Curva de aprendizagem Média (sintaxe de regras padronizada) Alta (linguagem de scripts própria)
Integração SIEM EVE JSON nativo (Splunk, ELK, Wazuh) TSV convertível; json-streams disponível
Melhor para Protecção activa, compliance, blocking Forense, threat hunting, baseline de tráfego

A estratégia recomendada para PME é usar os dois em camadas: Suricata em modo IPS no perímetro (firewall/gateway) para bloquear ameaças conhecidas, e Zeek em modo passivo (SPAN do switch core) para análise comportamental e forense. O Dia 20 deste curso cobre plataformas de monitorização que podem receber os logs de ambos.

8. Erros Comuns e Lista de Verificação

Os problemas mais frequentes ao implementar Suricata e Zeek em ambientes PME:

Problema Causa Solução
Suricata não gera alertas Interface de captura incorrecta no suricata.yaml Confirmar interface com ip a e corrigir a secção af-packet
Alertas em excesso (milhares por hora) Regras ET Open sem filtro; $HOME_NET mal definido Definir $HOME_NET corretamente no suricata.yaml; usar threshold.conf para suprimir regras ruidosas
Zeek não regista tráfego Interface em node.cfg incorrecta ou sem permissões Verificar interface em /opt/zeek/etc/node.cfg; correr zeekctl status
IPS bloqueia tráfego legítimo Falsos positivos em regras drop Mudar regras problemáticas para alert; testar em IDS antes de IPS
Performance degradada em IPS Batch size pequeno; CPU insuficiente Aumentar batchsize no suricata.yaml; afinar runmode: workers
Logs Zeek ocupam demasiado espaço Rotação não configurada Configurar LogRotationInterval e compressão; arquivar logs antigos

Antes de considerar a implementação completa, confirmar cada ponto:

  • ✓ Suricata instalado e versão verificada com suricata --build-info
  • ✓ Regras ET Open actualizadas com suricata-update
  • ✓ Variável $HOME_NET definida correctamente no suricata.yaml
  • ✓ Interface de captura confirmada (IDS passivo ou IPS via NFQueue)
  • ✓ EVE JSON a ser gerado em /var/log/suricata/eve.json
  • ✓ Zeek instalado e cluster activo (zeekctl status mostra workers running)
  • ✓ Logs Zeek a ser escritos em /opt/zeek/logs/current/
  • ✓ Rotação de logs configurada (evitar disco cheio)
  • ✓ IPS testado em modo IDS antes de activar blocking
  • ✓ Scripts Zeek customizados testados em ambiente de staging
  • ✓ Integração com SIEM/monitorização configurada (ver Dia 20)
# Verificacao rapida do Suricata
sudo systemctl status suricata
sudo tail -5 /var/log/suricata/eve.json | jq . | head -30

# Verificacao rapida do Zeek
sudo /opt/zeek/bin/zeekctl status
ls -la /opt/zeek/logs/current/conn.log

No próximo dia (Dia 22) abordaremos redes overlay — VXLAN, GENEVE e SD-WAN, tecnologias que criam redes virtuais por cima de infraestruturas existentes. Para complementar este artigo, o Dia 27 do Curso de Linux cobre hardening de sistema com fail2ban, auditd e Lynis — a camada de segurança do host que complementa a segurança de rede abordada aqui.

Artigos relacionados: