El filtro de paquetes de Berkeley ( BPF ; también conocido como filtro de paquetes BSD , BPF clásico o cBPF ) es un mecanismo de captura de red y filtro de paquetes que permite capturar y filtrar paquetes de red informática a nivel del sistema operativo . Proporciona una interfaz directa a las capas de enlace de datos , permitiendo el envío y la recepción de paquetes de la capa de enlace [ 1 ] , y permite que un proceso de espacio de usuario proporcione un programa de filtro que especifique qué paquetes desea recibir. Por ejemplo, un proceso tcpdump puede querer recibir solo paquetes que inicien una conexión TCP. BPF devuelve solo los paquetes que pasan el filtro proporcionado por el proceso. Esto evita copiar paquetes no deseados del núcleo del sistema operativo al proceso, mejorando considerablemente el rendimiento. El programa de filtro se presenta en forma de instrucciones para una máquina virtual , que son interpretadas, o compiladas a código máquina mediante un mecanismo justo a tiempo (JIT), y ejecutadas en el núcleo.
BPF es utilizado por programas que necesitan, entre otras cosas, analizar el tráfico de red. Si el controlador de la interfaz de red admite el modo promiscuo , permite que la interfaz se configure en ese modo para que se puedan recibir todos los paquetes de la red , incluso aquellos destinados a otros hosts.
El mecanismo de filtrado BPF está disponible en la mayoría de los sistemas operativos tipo Unix . A veces, BPF se utiliza para referirse únicamente al mecanismo de filtrado, en lugar de a toda la interfaz. Algunos sistemas, como Linux y Tru64 UNIX , proporcionan una interfaz sin procesar a la capa de enlace de datos distinta de la interfaz sin procesar BPF, pero utilizan los mecanismos de filtrado BPF para dicha interfaz.
El núcleo de Linux proporciona una versión extendida del mecanismo de filtrado BPF, denominada eBPF , que utiliza un mecanismo JIT y se emplea para el filtrado de paquetes, así como para otros fines en el núcleo. eBPF también está disponible para Microsoft Windows . [ 2 ]
Historia
El artículo original fue escrito por Steven McCanne y Van Jacobson en 1992 mientras estaban en el Laboratorio Lawrence Berkeley . [ 1 ] [ 3 ]
Interfaz de enlace de datos sin procesar
BPF proporciona pseudodispositivos que se pueden vincular a una interfaz de red; las lecturas del dispositivo leerán búferes llenos de paquetes recibidos en la interfaz de red, y las escrituras en el dispositivo inyectarán paquetes en la interfaz de red.
En 2007, Robert Watson y Christian Peron añadieron extensiones de búfer de copia cero a la implementación de BPF en el sistema operativo FreeBSD , [ 4 ] permitiendo que la captura de paquetes del kernel en el controlador de interrupciones del controlador del dispositivo escribiera directamente en la memoria del proceso de usuario para evitar la necesidad de dos copias de todos los datos del paquete recibidos a través del dispositivo BPF. Si bien una copia permanece en la ruta de recepción para los procesos de usuario, esto preserva la independencia de los diferentes consumidores del dispositivo BPF, además de permitir el empaquetado de las cabeceras en el búfer BPF en lugar de copiar los datos completos del paquete. [ 5 ]
Filtración
Las capacidades de filtrado de BPF se implementan como un intérprete de lenguaje máquina para la máquina virtual de BPF , una máquina de 32 bits con instrucciones de longitud fija, un acumulador y un registro de índice . Los programas en ese lenguaje pueden obtener datos del paquete, realizar operaciones aritméticas con ellos y comparar los resultados con constantes o con datos del paquete o bits de prueba en los resultados, aceptando o rechazando el paquete según los resultados de esas pruebas.
BPF se suele ampliar "sobrecargando" las instrucciones de carga (ld) y almacenamiento (str).
Las implementaciones tradicionales de BPF tipo Unix pueden utilizarse en el espacio de usuario, a pesar de haber sido escritas para el espacio del kernel. Esto se logra mediante condiciones de preprocesador .
Desde la versión 3.18, el kernel de Linux incluye una máquina virtual BPF extendida con diez registros de 64 bits, denominada eBPF . Puede utilizarse para fines distintos a la red, como adjuntar programas eBPF a diversos puntos de rastreo . [ 6 ] [ 7 ] [ 8 ] Desde la versión 3.19 del kernel, los filtros eBPF pueden adjuntarse a sockets , [ 9 ] [ 10 ] y, desde la versión 4.1 del kernel, a clasificadores de control de tráfico para la ruta de datos de red de entrada y salida. [ 11 ] [ 12 ] La versión original y obsoleta ha sido renombrada retroactivamente a BPF clásico ( cBPF ). Actualmente, el kernel de Linux ejecuta solo eBPF y el bytecode cBPF cargado se traduce de forma transparente a una representación eBPF en el kernel antes de la ejecución del programa. [ 13 ] Todo el bytecode se verifica antes de su ejecución para prevenir ataques de denegación de servicio. Hasta Linux 5.3, el verificador prohibía el uso de bucles para evitar tiempos de ejecución potencialmente ilimitados; ahora se permiten bucles con tiempo de ejecución limitado en los núcleos más recientes. [ 14 ]
Extensiones y optimizaciones
Algunos proyectos utilizan conjuntos de instrucciones BPF o técnicas de ejecución diferentes a las originales.
Algunas plataformas, como FreeBSD , NetBSD y WinPcap , utilizan un compilador justo a tiempo (JIT) para convertir las instrucciones BPF en código nativo y así mejorar el rendimiento. Linux incluye un compilador JIT para BPF que está desactivado por defecto.
Los intérpretes en modo kernel para ese mismo lenguaje de máquina virtual se utilizan en mecanismos de capa de enlace de datos sin procesar en otros sistemas operativos, como Tru64 Unix , y para filtros de sockets en el kernel de Linux y en el mecanismo de captura de paquetes WinPcap y Npcap .
Implementaciones
La implementación de la API pcap en libpcap/WinPcap/Npcap proporciona un intérprete en modo usuario para BPF. De esta forma, al capturar paquetes en sistemas sin soporte en modo kernel para este mecanismo de filtrado, los paquetes pueden filtrarse en modo usuario. El código que utiliza la API pcap funciona en ambos tipos de sistemas, aunque, en aquellos donde el filtrado se realiza en modo usuario, todos los paquetes, incluidos los que se filtrarán, se copian del kernel al espacio de usuario. Este intérprete también puede utilizarse para leer archivos que contienen paquetes capturados con pcap.
Otro intérprete en modo usuario es uBPF , que admite JIT y eBPF (sin cBPF). Su código se ha reutilizado para proporcionar soporte para eBPF en sistemas que no son Linux. [ 15 ] El eBPF de Microsoft en Windows se basa en uBPF y el verificador formal PREVAIL. [ 16 ] rBPF , una reescritura de uBPF en Rust, es utilizado por la plataforma blockchain Solana como motor de ejecución. [ 17 ]
Programación
El BPF clásico generalmente es emitido por un programa a partir de alguna regla textual de muy alto nivel que describe el patrón a coincidir. Una de estas representaciones se encuentra en libpcap . [ 18 ] El BPF clásico y el eBPF también pueden escribirse directamente como código máquina o utilizando un lenguaje ensamblador para una representación textual. Entre los ensambladores notables se incluyen la herramienta del kernel de Linux bpf_asm(cBPF), bpfc(cBPF) y el ubpfensamblador (eBPF). El bpftoolcomando también puede actuar como un desensamblador para ambas variantes de BPF. Los lenguajes ensambladores no son necesariamente compatibles entre sí.
El código de bytes eBPF se ha convertido recientemente en un objetivo para lenguajes de alto nivel. LLVM añadió soporte para eBPF en 2014, y GCC lo hizo en 2019. Ambos conjuntos de herramientas permiten compilar C y otros lenguajes compatibles a eBPF. Un subconjunto de P4 también se puede compilar a eBPF utilizando BCC, un conjunto de compiladores basado en LLVM. [ 19 ]
Seguridad
El ataque Spectre podría aprovechar el intérprete eBPF o el compilador JIT del kernel de Linux para extraer datos de otros procesos del kernel. [ 20 ] Una función de endurecimiento JIT en el kernel mitiga esta vulnerabilidad. [ 21 ]
El grupo chino de seguridad informática Pangu Lab afirmó que la NSA utilizó BPF para ocultar comunicaciones de red como parte de una compleja puerta trasera de Linux . [ 22 ]
Véase también
Referencias
- 1 2 McCanne, Steven; Jacobson, Van (1992-12-19). "El filtro de paquetes BSD: una nueva arquitectura para la captura de paquetes a nivel de usuario" (PDF) . Archivado (PDF) del original el 19-04-2009 . Recuperado el 25-05-2009 .
- ↑ «Microsoft adopta la superherramienta eBPF del kernel de Linux y la extiende para Windows» . The Register . 11 de mayo de 2021. Archivado del original el 11 de mayo de 2021.
- ↑ McCanne, Steven; Jacobson, Van (enero de 1993). "El filtro de paquetes BSD: una nueva arquitectura para la captura de paquetes a nivel de usuario" . USENIX . Archivado del original el 3 de agosto de 2020. Recuperado el 10 de junio de 2014 .
- ↑ "bpf(4) Filtro de paquetes de Berkeley" . FreeBSD . 15 de junio de 2010. Archivado del original el 21 de octubre de 2020. Consultado el 10 de junio de 2014 .
- ↑ Watson, Robert NM; Peron, Christian SJ (2007-03-09). "Zero-Copy BPF" (PDF) . Archivado (PDF) del original el 16-05-2008 . Recuperado el 29-07-2008 .
- ↑ "Núcleo de Linux 3.18, Sección 1.3. Llamada al sistema bpf() para programas de máquina virtual eBFP" . kernelnewbies.org . 7 de diciembre de 2014. Archivado del original el 25 de octubre de 2019. Consultado el 6 de septiembre de 2019 .
- ↑ Jonathan Corbet (24 de septiembre de 2014). "La API de llamadas al sistema BPF, versión 14" . LWN.net . Archivado del original el 27 de diciembre de 2014. Consultado el 19 de enero de 2015 .
- ↑ Jonathan Corbet (2 de julio de 2014). "Extending extended BPF" . LWN.net . Archivado del original el 24 de abril de 2019. Consultado el 19 de enero de 2015 .
- ↑ "Núcleo de Linux 3.19, Sección 11. Redes" . kernelnewbies.org . 8 de febrero de 2015. Archivado del original el 26 de febrero de 2025. Consultado el 13 de abril de 2025 .
- ↑ Jonathan Corbet (10 de diciembre de 2014). "Conexión de programas eBPF a sockets" . LWN.net . Archivado del original el 14 de febrero de 2015. Consultado el 13 de febrero de 2015 .
- ↑ "Núcleo de Linux 4.1, Sección 11. Redes" . kernelnewbies.org . 21 de junio de 2015. Archivado del original el 16 de octubre de 2015. Consultado el 17 de octubre de 2015 .
- ↑ "Guía de referencia de BPF y XDP" . cilium.readthedocs.io . 24 de abril de 2017. Archivado del original el 24 de abril de 2018. Consultado el 23 de abril de 2018 .
- ↑ "Guía de referencia de BPF y XDP — Documentación de Cilium 1.6.5" . docs.cilium.io . Archivado del original el 18 de septiembre de 2020. Consultado el 18 de diciembre de 2019 .
- ↑ "bpf: introduce bucles limitados" . git.kernel.org . 19 de junio de 2019. Archivado del original el 20 de agosto de 2022. Consultado el 19 de agosto de 2022 .
- ↑ "generic-ebpf/generic-ebpf" . GitHub . 28 de abril de 2022. Archivado del original el 27 de septiembre de 2020. Consultado el 4 de agosto de 2020 .
- ↑ "microsoft/ebpf-for-windows: implementación de eBPF que se ejecuta sobre Windows" . GitHub . Microsoft. 11 de mayo de 2021. Archivado del original el 11 de mayo de 2021. Consultado el 11 de mayo de 2021 .
- ↑ "Descripción general | Documentación de Solana" . Archivado del original el 31/01/2022 . Consultado el 31/01/2022 .
- ↑ "Sintaxis BPF" . biot.com . Archivado del original el 14 de agosto de 2020. Consultado el 3 de agosto de 2020 .
- ↑ "Sumérgete en BPF: una lista de material de lectura" . qmonnet.github.io . Archivado del original el 2 de octubre de 2019. Consultado el 4 de agosto de 2020 .
- ↑ "Lectura de memoria privilegiada con un canal lateral" . Equipo del Proyecto Zero en Google . 3 de enero de 2018. Archivado del original el 1 de octubre de 2019. Consultado el 20 de enero de 2018 .
- ↑ "bpf: introduce la configuración BPF_JIT_ALWAYS_ON" . git.kernel.org . Archivado del original el 19 de octubre de 2020. Consultado el 20 de septiembre de 2021 .
- ↑ "Anatomía de la presunta puerta trasera de alto nivel de la NSA oculta durante una década" . The Register . 23 de febrero de 2022. Archivado del original el 23 de febrero de 2022. Consultado el 24 de febrero de 2022 .
Lecturas adicionales
- McCanne, Steven; Jacobson, Van (1992-12-19). "El filtro de paquetes BSD: una nueva arquitectura para la captura de paquetes a nivel de usuario" (PDF) .
Enlaces externos
- – Manual de interfaces del kernel de FreeBSD – un ejemplo de BPF convencional
- bpfc, un compilador de Berkeley Packet Filter, desensamblador JIT de Linux BPF (parte de netsniff-ng)
- Documentación de BPF para el kernel de Linux
- Documentación de filtros de Linux , para formatos de código de bytes cBPF y eBPF.
- Software de red basado en el protocolo de Internet
- Paquetes (tecnología de la información)