Falco es un motor de detección de amenazas en tiempo de ejecución, proyecto graduado de la CNCF, que observa las llamadas al sistema del kernel y las compara con reglas para detectar comportamientos sospechosos: una shell abierta dentro de un contenedor, la lectura de /etc/shadow, un binario inesperado que se ejecuta. A diferencia de un escáner de imágenes como Trivy, Falco vigila lo que ocurre mientras los contenedores están en marcha. En este tutorial instalarás Falco en Ubuntu 24.04 con el driver eBPF moderno, provocarás alertas para comprobar que funciona, escribirás una regla propia y enviarás los avisos a Slack.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS (kernel 6.8), por ejemplo un VPS de CubePath, con un usuario no root con privilegios
sudo. - Al menos 2 GB de RAM y 1 vCPU.
- Docker Engine instalado, para las pruebas con contenedores y para ejecutar Falcosidekick.
- Opcional: un webhook entrante de Slack (Incoming Webhook) para el paso 6.
Paso 1: Añadir el repositorio de Falco
Descarga la clave de firma del proyecto en /etc/apt/keyrings:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | sudo gpg --dearmor -o /etc/apt/keyrings/falco-archive-keyring.gpg
Añade el repositorio estable:
echo "deb [signed-by=/etc/apt/keyrings/falco-archive-keyring.gpg] https://download.falco.org/packages/deb stable main" | sudo tee /etc/apt/sources.list.d/falcosecurity.list
Actualiza el índice de paquetes:
sudo apt update
Paso 2: Instalar Falco con el driver eBPF moderno
Falco necesita un driver para recibir los eventos del kernel. Hay tres opciones: módulo de kernel (kmod), sonda eBPF clásica (ebpf) y eBPF moderno (modern_ebpf). El eBPF moderno viene incluido en el propio binario, no necesita compilar nada ni cabeceras del kernel y funciona en kernels 5.8 o superiores con BTF, como el de Ubuntu 24.04. Comprueba que tu kernel expone BTF:
ls /sys/kernel/btf/vmlinux
/sys/kernel/btf/vmlinux
El paquete muestra un diálogo para elegir el driver. Para instalar sin preguntas y con el driver eBPF moderno:
sudo FALCO_FRONTEND=noninteractive FALCO_DRIVER_CHOICE=modern_ebpf apt install -y falco
Con este driver el servicio se llama falco-modern-bpf. Actívalo y arráncalo:
sudo systemctl enable --now falco-modern-bpf.service
systemctl status falco-modern-bpf --no-pager
● falco-modern-bpf.service - Falco: Container Native Runtime Security with modern ebpf
Loaded: loaded (/usr/lib/systemd/system/falco-modern-bpf.service; enabled; preset: enabled)
Active: active (running)
Revisa el arranque en el journal. Debe cargar las reglas y abrir la fuente de eventos con la sonda moderna:
sudo journalctl -u falco-modern-bpf -n 20 --no-pager
Loading rules from:
/etc/falco/falco_rules.yaml | schema validation: ok
Opening 'syscall' source with modern BPF probe.
Paso 3: Provocar alertas de prueba
Deja el journal abierto en una terminal:
sudo journalctl -u falco-modern-bpf -f
En otra terminal, lee un archivo sensible desde el host:
sudo cat /etc/shadow > /dev/null
Falco dispara la regla Read sensitive file untrusted:
Warning Sensitive file opened for reading by non-trusted program (file=/etc/shadow gparent=bash ggparent=sshd evt_type=openat user=root user_uid=0 process=cat proc_exepath=/usr/bin/cat parent=sudo command=cat /etc/shadow ...)
Ahora arranca un contenedor y abre una shell interactiva dentro:
docker run -d --name prueba nginx:alpine
docker exec -it prueba sh
Sal de la shell con exit. En el journal aparece la regla Terminal shell in container, con el nombre y la imagen del contenedor:
Notice A shell was spawned in a container with an attached terminal (evt_type=execve user=root process=sh ... container_name=prueba container_image_repository=docker.io/library/nginx ...)
Elimina el contenedor de prueba:
docker rm -f prueba
Paso 4: Configurar la salida de alertas
La configuración principal está en /etc/falco/falco.yaml. No lo sustituyas entero: cambia solo las claves necesarias. Ábrelo:
sudo nano /etc/falco/falco.yaml
Busca estas claves y deja sus valores así. json_output hace que cada alerta sea un objeto JSON, más fácil de procesar, y file_output guarda además una copia en disco:
json_output: true
file_output:
enabled: true
keep_alive: false
filename: /var/log/falco_events.json
El nivel mínimo de alerta se controla con la clave priority (por defecto debug, es decir, todo). Si solo quieres avisos a partir de cierta gravedad, súbelo, por ejemplo a notice.
Reinicia el servicio y comprueba que arranca sin errores:
sudo systemctl restart falco-modern-bpf
systemctl is-active falco-modern-bpf
active
Repite sudo cat /etc/shadow > /dev/null y comprueba que la alerta llega al archivo:
sudo tail -n 1 /var/log/falco_events.json
{"hostname":"servidor","output":"... Warning Sensitive file opened for reading by non-trusted program ...","priority":"Warning","rule":"Read sensitive file untrusted","source":"syscall","tags":[...],"time":"2026-09-25T10:15:02.123456789Z","output_fields":{...}}
Paso 5: Escribir reglas propias
Las reglas incluidas están en /etc/falco/falco_rules.yaml y se sobrescriben al actualizar el paquete. Tus reglas van en /etc/falco/falco_rules.local.yaml, que Falco carga después y que el paquete no toca.
Una regla tiene nombre, descripción, condición, mensaje de salida y prioridad. La condición combina campos de eventos (proc.name, container.id, fd.name...) con macros ya definidas en las reglas por defecto, como spawned_process (un proceso nuevo se ha ejecutado) o container (el evento ocurre dentro de un contenedor).
Abre el archivo de reglas locales:
sudo nano /etc/falco/falco_rules.local.yaml
Añade una regla que detecte herramientas de reconocimiento de red ejecutadas dentro de un contenedor, algo que una aplicación normal no hace:
- list: herramientas_red
items: [nc, ncat, netcat, nmap, masscan, socat]
- rule: Herramienta de red ejecutada en contenedor
desc: Detecta la ejecución de utilidades de reconocimiento o túneles de red dentro de un contenedor
condition: spawned_process and container and proc.name in (herramientas_red)
output: Herramienta de red en contenedor (proceso=%proc.name cmdline=%proc.cmdline usuario=%user.name contenedor=%container.name imagen=%container.image.repository)
priority: WARNING
tags: [container, network]
Si una regla por defecto genera demasiado ruido en tu entorno, puedes desactivarla en este mismo archivo por su nombre:
- rule: Read sensitive file untrusted
enabled: false
Hazlo solo si has confirmado que las alertas son falsos positivos. Valida las reglas antes de reiniciar. Hay que cargar también el archivo por defecto, porque tu regla usa sus macros:
sudo falco -V /etc/falco/falco_rules.yaml -V /etc/falco/falco_rules.local.yaml
Si no hay errores, reinicia Falco y prueba la regla. La imagen alpine incluye nc como parte de BusyBox:
sudo systemctl restart falco-modern-bpf
docker run --rm alpine nc -h
sudo journalctl -u falco-modern-bpf -n 5 --no-pager | grep "Herramienta de red"
La alerta debe aparecer con proceso=nc y la imagen alpine.
Paso 6: Enviar alertas a Slack con Falcosidekick
Falco puede enviar cada alerta por HTTP, pero Slack espera un formato distinto. Falcosidekick es el componente oficial que recibe las alertas de Falco y las reenvía a Slack, Teams, correo, Loki y decenas de destinos más.
Ejecuta Falcosidekick en Docker, escuchando solo en localhost. Sustituye la URL por la de tu webhook de Slack:
docker run -d --name falcosidekick --restart unless-stopped \
-p 127.0.0.1:2801:2801 \
-e SLACK_WEBHOOKURL="https://hooks.slack.com/services/your_webhook_path" \
-e SLACK_MINIMUMPRIORITY=warning \
falcosecurity/falcosidekick
SLACK_MINIMUMPRIORITY=warning evita que las alertas de nivel notice o inferior lleguen al canal. Envía un evento de prueba para confirmar que el webhook funciona:
curl -s -X POST http://127.0.0.1:2801/test
Debe aparecer un mensaje de prueba en tu canal de Slack. Ahora indica a Falco que envíe las alertas a Falcosidekick. Abre de nuevo la configuración:
sudo nano /etc/falco/falco.yaml
Localiza la sección http_output y déjala así (necesita json_output: true, que ya activaste en el paso 4):
http_output:
enabled: true
url: http://127.0.0.1:2801/
Reinicia Falco y provoca una alerta de prioridad Warning:
sudo systemctl restart falco-modern-bpf
sudo cat /etc/shadow > /dev/null
La alerta llega a Slack en unos segundos. Puedes ver lo que recibe Falcosidekick con docker logs falcosidekick.
Falco en Kubernetes
En un clúster, Falco se despliega como DaemonSet con su chart oficial de Helm, uno por nodo, y el chart puede desplegar Falcosidekick al mismo tiempo:
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install falco falcosecurity/falco \
--namespace falco --create-namespace \
--set driver.kind=modern_ebpf \
--set falcosidekick.enabled=true \
--set falcosidekick.config.slack.webhookurl="https://hooks.slack.com/services/your_webhook_path" \
--set falcosidekick.config.slack.minimumpriority=warning
Comprueba que hay un pod de Falco por nodo:
kubectl get pods -n falco -o wide
Las reglas propias se añaden con el valor customRules del chart, en un archivo de valores que pasas con -f.
Solución de problemas
El servicio no arranca y el journal menciona BPF o BTF: el kernel no expone /sys/kernel/btf/vmlinux (ocurre con kernels personalizados). Usa el módulo de kernel: instala las cabeceras con sudo apt install linux-headers-$(uname -r), reinstala con sudo FALCO_FRONTEND=noninteractive FALCO_DRIVER_CHOICE=kmod apt install --reinstall -y falco y usa el servicio falco-kmod.
Falco no arranca tras editar reglas: casi siempre es un error de sintaxis YAML o una macro inexistente. Ejecuta la validación con falco -V del paso 5; indica el archivo y la línea.
Las alertas no muestran el nombre del contenedor: Falco obtiene los metadatos del runtime de contenedores a través de su socket. Comprueba que Docker (o containerd) está en marcha y revisa en el journal de Falco si hay errores de conexión al socket.
No llegan alertas a Slack: comprueba que curl -X POST http://127.0.0.1:2801/test funciona, que json_output y http_output están activados y revisa docker logs falcosidekick. Recuerda que las alertas por debajo de SLACK_MINIMUMPRIORITY se descartan.
Consumo de CPU alto: se debe normalmente a reglas muy genéricas en servidores con mucha actividad. Afina las condiciones con excepciones concretas (procesos o imágenes conocidos) en lugar de desactivar reglas enteras.
Conclusión
Tienes Falco vigilando las llamadas al sistema del servidor con el driver eBPF moderno, una regla propia para contenedores y las alertas relevantes llegando a Slack a través de Falcosidekick. Como siguientes pasos, puedes activar falcoctl para actualizar automáticamente las reglas oficiales, ajustar las reglas por defecto a tus cargas con excepciones, y combinar Falco con el escaneo previo de imágenes con Trivy para cubrir tanto el build como la ejecución.
