4

Como Montar um SIEM Doméstico no Linux com Detecção de Intrusos ARP e Fabricante OUI

Fala pessoal!

Quem aqui tem servidor em casa ou vários dispositivos conectados já deve ter passado por aquela situação clássica: abrir o painel do roteador da operadora e dar de cara com uma lista de MACs misteriosos conectados na rede, sem saber se aquilo é uma lâmpada inteligente, um aparelho da sua casa ou alguém que descobriu a senha do seu Wi-Fi.

A maioria dos firmwares comerciais é horrível para isso. Eles demoram para atualizar o lease do DHCP, não alertam em tempo real e não resolvem quem é o fabricante do hardware.

Recentemente estruturei um "Micro-SIEM" caseiro em Python para rodar 24h no meu servidor local (um mini PC com Linux) e queria compartilhar a lógica enxuta que usei, porque ela não consome nada de CPU e avisa na hora quando qualquer aparelho desconhecido conecta.

Como funciona sem pesar o sistema?

Muita gente tenta rodar Nmap em loop, mas isso gera muito ruído na LAN e pode travar módulos ESP8266/ESP32 de lâmpadas e tomadas inteligentes.

A sacada é usar o que o próprio kernel do Linux já faz nativamente:

  1. Leitura direta do /proc/net/arp: O kernel mantém a tabela ARP na memória RAM. Ler esse arquivo pseudo-sistema consome 0% de CPU.
  2. Ping sweep assíncrono rápido: A cada 3 minutos, um script em asyncio dispara pings rápidos em lote na sub-rede /24. A varredura completa dura menos de 2 segundos.
  3. Resolução de Fabricante IEEE OUI Offline: Cruzando os primeiros 3 octetos do MAC (ex: EC:FA:BC para chips Espressif de IoT, DC:A6:32 para Raspberry Pi, 24:4C:E3 para Samsung), o sistema já classifica o tipo de dispositivo sem depender de nenhuma API externa.

O script base em Python:

import os
import asyncio

OUI_DATABASE = {
    "DC:A6:32": "Raspberry Pi",
    "EC:FA:BC": "Espressif (Tuya/IoT)",
    "30:AE:A4": "Espressif Systems",
    "AC:D1:B8": "Apple, Inc.",
    "24:4C:E3": "Samsung",
    "18:66:DA": "Intel",
}

def resolve_vendor(mac: str) -> str:
    prefix = mac.upper()[:8]
    return OUI_DATABASE.get(prefix, "Desconhecido")

def get_arp_devices():
    devices = []
    if not os.path.exists("/proc/net/arp"):
        return devices
    with open("/proc/net/arp", "r") as f:
        for line in f.readlines()[1:]:
            parts = line.split()
            if len(parts) >= 6 and parts[2] == "0x2" and parts[3] != "00:00:00:00:00:00":
                devices.append({
                    "ip": parts[0],
                    "mac": parts[3].upper(),
                    "interface": parts[5],
                    "vendor": resolve_vendor(parts[3])
                })
    return devices

async def ping_sweep(subnet="192.168.1"):
    async def ping(ip):
        proc = await asyncio.create_subprocess_exec(
            "ping", "-c", "1", "-W", "1", ip,
            stdout=asyncio.subprocess.DEVNULL, stderr=asyncio.subprocess.DEVNULL
        )
        await proc.wait()
    await asyncio.gather(*[ping(f"{subnet}.{i}") for i in range(1, 255)])

Ao comparar a lista atual com a anterior armazenada em banco (ou JSON simples), no instante em que surge um MAC inédito, o script dispara um evento NEW_DEVICE para notificação ou isolamento.


Escrevi o artigo com a integração completa de serviço no systemd e práticas de quarentena de rede lá no meu blog:

👉 Tutorial Completo: Sentinela de Rede no Fymax Sentinel

Como vocês fazem o monitoramento de rede e inventário de nós no laboratório ou na casa de vocês? Usam alguma solução pronta como Wazuh/Pi-hole ou também preferem automações sob medida?

Carregando publicação patrocinada...
1