Ver el interior del núcleo: cómo Nexusguard usa eBPF para una observabilidad y seguridad de alta precisión

Gao Shen
Nexusguard
-
8 minutos de lectura
Share to:

Un análisis práctico de cómo eBPF permite una observabilidad precisa y de bajo costo en las plataformas de seguridad modernas

Introducción: Por qué la observabilidad falla en los sistemas de seguridad modernos

Cuando algo va mal en la producción, el problema rara vez es que no lo sabemos algo sucedió. Los picos de CPU, el aumento de la latencia, la pérdida de paquetes: los sistemas de monitoreo tradicionales son muy buenos para decirnos eso.

En lo que son mucho menos eficaces es en responder a la pregunta que más importa durante un incidente:

¿Qué pasó exactamente dentro del sistema, en el momento en que ocurrió?

Para las plataformas de seguridad modernas, especialmente aquellas que operan a escala, dentro de entornos en contenedores y en condiciones de ataque, esta brecha es crítica. Muchos comportamientos importantes se producen en las profundidades del núcleo de Linux o a lo largo de las rutas de ejecución de las aplicaciones, áreas que, de hecho, son invisibles para las herramientas del espacio de usuario y las métricas muestreadas.

En Nexusguard, una de las tecnologías clave en las que confiamos para cerrar esta brecha es eBPF.

¿Qué es eBPF?

eBPF (filtro de paquetes extendido de Berkeley) puede entenderse como un máquina virtual en espacio aislado que se ejecuta dentro del kernel de Linux.

Permite a los desarrolladores cargar dinámicamente pequeños programas en un núcleo en ejecución, donde pueden observar y reaccionar de forma segura a los eventos del sistema, sin modificar el código fuente del núcleo, cargar los módulos del núcleo ni reiniciar el sistema.

Figura 1: Descripción conceptual del eBPF

Este diagrama ilustra dónde se ejecutan los programas de eBPF dentro del núcleo de Linux, cómo se verifican y compilan mediante JIT y cómo los datos fluyen de forma segura al espacio de usuario a través de mapas de eBPF.

Tres propiedades principales hacen que el eBPF sea viable para los sistemas de producción:

Seguridad desde el diseño

Todos los programas de eBPF deben pasar un verificador del núcleo antes de poder ejecutarse. El verificador garantiza que los programas no puedan bloquear el núcleo, entrar en bucles infinitos ni acceder a memoria no válida. Esta es una diferencia fundamental con respecto a los módulos del núcleo tradicionales, en los que un solo error puede provocar la caída de todo el sistema.

Alto rendimiento

Una vez verificados, los programas eBPF se compilan mediante JIT en código máquina nativo. Esto les permite ejecutarse con una sobrecarga muy baja y sin el cambio constante de contexto entre el usuario y el núcleo que requieren muchas herramientas de rastreo tradicionales.

Instrumentación sin tiempo de inactividad

Los programas eBPF se pueden cargar y descargar de forma dinámica, lo que permite el diagnóstico y la observabilidad en tiempo real sin interrumpir el servicio.

Cómo funciona eBPF en la práctica

Desde una perspectiva de ingeniería, un flujo de trabajo típico de eBPF tiene este aspecto:

  1. Se escribe un programa eBPF (normalmente en C o mediante marcos como BCC o bpftrace).
  2. El programa se compila en código de bytes eBPF.
  3. El código de bytes se carga en el núcleo mediante la llamada al sistema bpf ().
  4. El verificador del núcleo realiza comprobaciones de seguridad.
  5. El programa está compilado mediante JIT en código de máquina nativo
  6. El programa se adjunta a un evento específico.
  7. Cuando se produce el evento, el programa ejecuta y registra los datos.

Los datos recopilados generalmente se escriben en Mapas eBPF, que actúan como canal de comunicación entre los programas eBPF del espacio del núcleo y las aplicaciones del espacio de usuario.

Por qué son importantes los mapas eBPF

De forma predeterminada, los programas de eBPF no tienen estado. Cada ejecución se ejecuta de forma independiente y no puede recordar lo que ocurrió anteriormente. Los mapas de eBPF resuelven esta limitación.

Figura 2: Mapas de eBPF como puente de comunicaciones

Los mapas eBPF actúan como el principal puente de comunicación entre los programas eBPF del espacio del núcleo y los consumidores del espacio de usuario, lo que permite el estado, la agregación y el intercambio controlado de datos.

Los mapas eBPF son almacenes de valores clave residentes en el núcleo que permiten:

  • Estado persistente en todos los eventos
  • Agregación y recuento
  • Intercambio seguro de datos entre programas de eBPF
  • Acceso controlado desde el espacio de usuario

Sin mapas, el eBPF se limitaría a observaciones transitorias. Con los mapas, se convierte en la base de los sistemas reales de observación y monitoreo.

Tabla 1: Tipos de mapas eBPF

Tipo de Mapa Características Principales Casos de Uso Típicos
Tabla Hash Almacenamiento clave-valor, búsqueda O(1), sin orden Contadores, seguimiento de estados, almacenamiento de configuraciones
Arreglo (Array) Tamaño fijo, acceso por índice, eficiente en memoria Contadores globales, arreglos de métricas, banderas
Perf Event Array Basado en ring-buffer, transferencia eficiente de kernel a usuario Análisis de rendimiento, exportación de eventos de trazado
Ring Buffer Productor único, múltiples consumidores, mayor eficiencia de memoria Entrega de eventos de alto rendimiento (recomendado para nuevos diseños)
LRU Hash Expulsa automáticamente las entradas menos recientemente usadas Implementaciones de caché, seguimiento de estado de sesiones
LPM Trie Algoritmo de coincidencia de prefijo más largo Tablas de enrutamiento IP, coincidencia de reglas de firewall
Filtro de Bloom Prueba probabilística de pertenencia, extremadamente eficiente en espacio Deduplicación, verificaciones de existencia
Cola / Pila (Queue / Stack) Estructuras FIFO (cola) / LIFO (pila) Colas de eventos, búfer de mensajes
Sockmap / Sockhash Mapas conscientes de sockets para redirección y aceleración Balanceo de carga de red, redirección de tráfico

Apegarse a la realidad: desencadenantes de eventos

Los programas eBPF se ejecutan en respuesta a los eventos. Los tres mecanismos de apego más utilizados son:

sondas K

Sondeos dinámicos que se conectan a casi cualquier función del núcleo. Ofrecen una gran flexibilidad, pero pueden ser sensibles a los cambios de versión del kernel.

Sondas alcistas

Sondeos de espacio de usuario que se conectan a funciones dentro de los binarios de las aplicaciones. Permiten inspeccionar en profundidad el comportamiento de las aplicaciones sin modificar el código de la aplicación.

Puntos de seguimiento

Ganchos de núcleo definidos estáticamente con interfaces estables y menos sobrecarga. Cambian la flexibilidad por la estabilidad a largo plazo.

En los sistemas del mundo real, estos mecanismos suelen combinarse según los requisitos de rendimiento, estabilidad y observabilidad.

Tabla 2: Comparación de los mecanismos de eBPF
En los sistemas de producción, estos mecanismos suelen combinarse para equilibrar la estabilidad, la visibilidad y la sobrecarga de rendimiento.

Característica Kprobe Uprobe Tracepoint
Alcance Espacio kernel Espacio usuario Espacio kernel
Tipo Trazado dinámico Trazado dinámico Trazado estático
Flexibilidad Extremadamente alta (se puede asociar a casi cualquier función del kernel) Extremadamente alta (se puede asociar a casi cualquier instrucción o función) Limitada (solo tracepoints predefinidos)
Estabilidad Baja (puede cambiar entre versiones del kernel) Baja (puede cambiar entre versiones de la aplicación) Alta (ABI estable)
Sobrecarga de rendimiento Relativamente alta Relativamente alta Baja
Facilidad de uso Media Media Fácil (estructuras bien definidas)
Ejemplo kprobe:vfs_read uprobe:/bin/bash:readline tracepoint:syscalls:sys_enter_open

De herramientas genéricas a diagnósticos reales

El ecosistema eBPF incluye herramientas poderosas como:

  • herramientas bcc (por ejemplo, tcptop, execsnoop)
  • bpf trace, que permite que los programas de eBPF se escriban de forma similar a un script

Estas herramientas permiten:

  • Observa el comportamiento de la red en tiempo real
  • Capture los eventos de creación de procesos que las herramientas tradicionales pasan por alto
  • Mida la latencia de ejecución a nivel de función sin modificar el código de la aplicación

En un escenario de diagnóstico real, utilizamos bpftrace para rastrear el tiempo de ejecución de una función específica dentro de un motor WAF. Esto nos permitió identificar cuellos de botella en el rendimiento que habría sido extremadamente difícil de aislar utilizando únicamente registros o muestras de métricas, todo ello sin tener que volver a compilar ni volver a implementar la aplicación.

Para ilustrar cómo eBPF puede observar el comportamiento del espacio de usuario sin cambiar el código, considere el siguiente ejemplo simplificado.

func randomSleep() {

       duration := time.Duration(rand.Intn(3000)) * time.Millisecond // 0-3000ms

       time.Sleep(duration)

}

El siguiente script de bpftrace se adjunta a la función en tiempo de ejecución y mide su latencia de ejecución, sin volver a compilar ni reiniciar la aplicación.

#!/usr/bin/env bpftrace

/*

* bpftrace script: Monitor randomSleep function execution time

*

* Usage:

* sudo bpftrace monitor_timing.bt -p <PID>

*/

uprobe:./main:main.randomSleep

{

   @start[tid] = nsecs;

}

uretprobe:./main:main.randomSleep

{

   $duration_ms = (nsecs - @start[tid]) / 1000000; // Convert to milliseconds

   printf("randomSleep execution time: %llu ms\n", $duration_ms);

   

   // Statistics: total calls and average time

   @calls = count();

   @avg_time = avg($duration_ms);

   

   delete(@start[tid]);

}

BEGIN

{

   printf("Starting to monitor randomSleep function execution time...\n");

   printf("Press Ctrl+C to stop monitoring\n\n");

}

END

{

   printf("\n=== Statistics ===\n");

   printf("Total calls: ");

   print(@calls);

   printf("Average execution time: ");

   print(@avg_time);

   printf(" ms\n");

   printf("==================\n");

}

Figura 3: Captura de pantalla real del terminal

Salida de bpftrace en tiempo real que muestra la latencia de ejecución de funciones en tiempo real, recopilada de un proceso en ejecución sin instrumentación de aplicaciones.

Por qué construimos un monitor eBPF en Nexusguard

A medida que nuestra plataforma evolucionó, se hicieron evidentes varias limitaciones con los enfoques de monitoreo tradicionales:

  • Las herramientas de recopilación de métricas a menudo producían grandes volúmenes de datos que no necesitábamos, mientras que faltaban las métricas que importaban.
  • La ejecución basada en el muestreo introdujo imprecisiones.
  • La supervisión de la lógica específica de la empresa requería cambios de código intrusivos.
  • Soporte limitado e inconsistente para la observabilidad a nivel de contenedor y grupo.

Para abordar esto, construimos un Monitor eBPF adaptado a las necesidades operativas de Nexusguard.

Figura 4: Arquitectura eBPF de Nexusguard

Una vista simplificada de la arquitectura eBPF Monitor de Nexusguard, que muestra cómo los módulos eBPF residentes en el kernel recopilan datos basados en eventos, comparten el estado a través de mapas y exportan métricas estructuradas a sistemas de espacio de usuario.

A un alto nivel:

  • Los módulos eBPF se ejecutan dentro del núcleo y recopilan datos basados en eventos.
  • La configuración se pasa de forma dinámica a través de mapas eBPF.
  • Los datos recopilados se exportan al espacio de usuario, se transforman en métricas y se integran con las canalizaciones de monitoreo existentes.
  • El sistema se adapta dinámicamente a los reinicios de contenedores y procesos sin necesidad de cambios en el programa eBPF.

Seguridad, control de recursos y uso de producción

La ejecución de instrumentación dentro del núcleo naturalmente plantea preocupaciones sobre la seguridad y los gastos generales.

eBPF aborda estas preocupaciones a través de:

  • Límites estrictos impuestos por el verificador
  • Tiempo de ejecución limitado
  • Acceso controlado a la memoria
  • Comportamiento de ejecución predecible

Estas restricciones permiten que la observabilidad profunda se implemente con confianza en los entornos de producción.

Qué significa esto para los clientes de Nexusguard

Al aprovechar eBPF como parte de la arquitectura de nuestra plataforma, Nexusguard puede:

  • Observe el comportamiento donde realmente ocurre
  • Diagnostique los problemas más rápido y con menos suposiciones
  • Reduzca la dependencia de técnicas de depuración invasivas
  • Mantenga el rendimiento incluso con cargas pesadas

Para los clientes, esto se traduce en una mayor confiabilidad, una respuesta más rápida a los incidentes y decisiones de protección más precisas.

Reflexiones finales

A medida que los sistemas se vuelven más dinámicos y los ataques más sofisticados, la observabilidad debe acercarse más a la propia ruta de ejecución.

El eBPF nos brinda esa capacidad.

En Nexusguard, no se trata de una función independiente, sino de una tecnología fundamental que refuerza la forma en que construimos, operamos y desarrollamos nuestra plataforma de seguridad, de forma silenciosa, segura y precisa dentro del núcleo.

Protect Your Infrastructure Today

Explore Nexusguard Edge Protection Solutions Today