← Blog

Bloqueo automático de atacantes con BGP: un IDS que anuncia rutas de agujero negro

DEENESRUUK

El lugar más limpio para desviar un ataque no es el servidor, sino el borde de la red, antes de que los paquetes le cuesten nada. Suri Defender hace exactamente eso: convierte "esta IP nos está atacando" en un anuncio BGP que pone en agujero negro (black-holes) la fuente en los bordes y el MikroTik, mientras que el router central nunca lleva una sola ruta de agujero negro.

La idea: detección → una ruta

Bloquear con iptables funciona en una caja. Pero cuando ejecutas un sistema autónomo (AS 48756 aquí), el primitivo correcto es RTBH — Remote-Triggered Black Hole. Anuncias el /32 infractor sobre iBGP etiquetado con una comunidad de agujero negro (48756:666); cada router de borde que lo escucha descarta el tráfico hacia ese destino. Un anuncio, descartado en todas partes, a velocidad de línea.

Así que todo el diseño es un pipeline que termina en un announce BGP:

SSH / nginx / syslog / FortiGate logs
        │                    │
   CrowdSec scenarios    fail2ban jails
        │ decisiones          │ acción solo archivo
        ▼                    ▼
   DB fuente-de-verdad  +  archivos de prefijo
        │  unión − whitelist
        ▼
   ExaBGP route-injector  →  FRR (bgpd)  →  bordes / MikroTik
        announce /32 · community 48756:666
  • CrowdSec analiza los registros y ejecuta escenarios de detección, exponiendo un flujo de decisiones.
  • fail2ban maneja sus propias cárceles (SSH, VPN, nginx, mail) y adjunta los /32 baneados a un archivo plano: una acción deliberadamente simple basada solo en archivos, sin vtysh.
  • Un pequeño servicio FastAPI + SQLite mantiene la fuente de verdad, aplica TTLs y regenera el archivo de prefijos.
  • ExaBGP lee la unión de esos archivos (menos una lista blanca) y emite announce/withdraw a FRR, que refleja las rutas hacia adelante.

Por qué un route-injector supera a un reconciliador

La primera versión mantenía los agujeros negros como rutas estáticas más una prefix-list y redistribute static, con un reconciliador intentando mantenerlos sincronizados. Bajo FRR 10.6 eso luchaba constantemente contra el demonio de gestión: desincronizaciones del árbol de prefijos, rutas fantasma, contención de bloqueo de almacén de datos, un frr.conf de 2.6 MB.

Moverse a un ExaBGP route-injector eliminó por completo el estado de enrutamiento local: el núcleo no mantiene ninguna ruta de agujero negro ahora. "Bloqueado" y "anunciado" se convirtieron en el mismo hecho por construcción, no dos estados que un reconciliador tiene que perseguir. Ese es el tipo de invariante que hace que un sistema deje de sorprenderte a las 3 a.m.

Más ligero, también

Reemplazó una pesada pila Suricata + OpenSearch + Dashboards + Filebeat + EveBox —de unos 2.7 GB de RAM— con un puñado de procesos pequeños que suman unos pocos cientos de megabytes. Mismo trabajo, un orden de magnitud menos peso, y una única interfaz web para ver qué está en agujero negro actualmente y por qué.

La detección es un problema resuelto-ish; la parte interesante es la respuesta, y para una red, la respuesta más elegante es una ruta.

Transparencia: la mayoría de las entradas se redactan con ayuda de IA, y las versiones que no están en inglés se traducen automáticamente con un LLM local y luego se revisan. ¿Has visto un error? Avísame, por favor.