El filtro de paquetes de Berkeley ( BPF ) es una tecnología utilizada en ciertos sistemas operativos de los ordenadores para los programas que necesitan, entre otras cosas, analizar el tráfico de red (y EBPF es un BPF extendida JIT máquina virtual en el núcleo de Linux ). Proporciona una interfaz sin procesar para las capas de enlace de datos , lo que permite enviar y recibir paquetes de la capa de enlace sin procesar. [1] BPF está disponible en la mayoría de los sistemas operativos tipo Unix y eBPF para Linux y Microsoft Windows . [2] Además, si el controlador de la interfaz de red admite el modo promiscuo, permite poner la interfaz en ese modo para que se puedan recibir todos los paquetes de la red , incluso los destinados a otros hosts.
Desarrollador (es) | Steven McCanne, Van Jacobson |
---|---|
Versión inicial | 19 de diciembre de 1992 |
Sistema operativo | Tipo Unix , Windows |
BPF admite el filtrado de paquetes, lo que permite que un proceso de espacio de usuario proporcione un programa de filtrado que especifica qué paquetes desea recibir. Por ejemplo, un proceso tcpdump puede querer recibir solo paquetes que inician una conexión TCP. BPF solo devuelve paquetes que pasan el filtro que suministra el proceso. Esto evita copiar paquetes no deseados del kernel del sistema operativo al proceso, mejorando enormemente el rendimiento.
BPF a veces se usa para referirse solo al mecanismo de filtrado, en lugar de a toda la interfaz. Algunos sistemas, como Linux y Tru64 UNIX , proporcionan una interfaz sin formato a la capa de enlace de datos distinta de la interfaz sin formato BPF, pero utilizan los mecanismos de filtrado BPF para esa interfaz sin formato.
Interfaz sin formato
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 agregaron extensiones de búfer de copia cero a la implementación de BPF en el sistema operativo FreeBSD , [3] permitiendo la captura de paquetes del kernel en el controlador de interrupciones del controlador de dispositivo para escribir directamente en la memoria de proceso del usuario para evitar el requisito. para dos copias de todos los paquetes de datos recibidos a través del dispositivo BPF. Si bien una copia permanece en la ruta de recepción para los procesos del usuario, esto preserva la independencia de los diferentes consumidores de dispositivos BPF, además de permitir el empaquetado de encabezados en el búfer BPF en lugar de copiar los datos completos del paquete. [4]
Filtración
Las capacidades de filtrado de BPF se implementan como un intérprete de un lenguaje de máquina para la máquina virtual BPF , una máquina de 32 bits con instrucciones de longitud fija, un acumulador y un registro de índice . Los programas en ese idioma pueden obtener datos del paquete, realizar operaciones aritméticas con datos del paquete y comparar los resultados con constantes o con datos en el paquete o bits de prueba en los resultados, aceptando o rechazando el paquete en función de los resultados de esos pruebas.
BPF a menudo se amplía "sobrecargando" las instrucciones de carga (ld) y almacenamiento (str).
Las implementaciones tradicionales de BPF similares a Unix se pueden usar en el espacio de usuario, a pesar de estar escritas para el espacio del kernel. Esto se logra utilizando las condiciones del preprocesador .
Extensiones y optimizaciones
Algunos proyectos utilizan conjuntos de instrucciones BPF o técnicas de ejecución diferentes a las originales.
Algunas plataformas, incluidas FreeBSD , NetBSD y WinPcap , utilizan un compilador Just-In-Time (JIT) para convertir instrucciones BPF en código nativo con el fin de mejorar el rendimiento. Linux incluye un compilador BPF JIT que está deshabilitado de forma predeterminada.
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 socket en el kernel de Linux y en el mecanismo de captura de paquetes WinPcap y Npcap .
Desde la versión 3.18, el kernel de Linux incluye una máquina virtual BPF extendida con diez registros de 64 bits, denominada BPF extendida ( eBPF ). Se puede utilizar para fines que no sean de red, como para adjuntar programas eBPF a varios puntos de seguimiento . [5] [6] [7] Desde la versión 3.19 del kernel, los filtros eBPF se pueden adjuntar a los sockets , [8] [9] y, desde la versión 4.1 del kernel, a los clasificadores de control de tráfico para la ruta de datos de entrada y salida de la red. [10] [11] La versión original y obsoleta ha sido renombrada retroactivamente a BPF clásico ( cBPF ). Hoy en día, el kernel de Linux solo ejecuta eBPF y el código de bytes cBPF cargado se traduce de forma transparente en una representación de eBPF en el kernel antes de la ejecución del programa. [12] Todo el código de bytes se verifica antes de ejecutarse para evitar ataques de denegación de servicio. Hasta Linux 5.3, el verificador prohibió el uso de bucles.
Se proporciona un intérprete de modo de usuario para BPF con la implementación libpcap / WinPcap / Npcap de la API de pcap , de modo que, al capturar paquetes en sistemas sin soporte de modo kernel para ese mecanismo de filtrado, los paquetes se pueden filtrar en modo de usuario; El código que utiliza la API de pcap funcionará en ambos tipos de sistemas, aunque, en los sistemas donde el filtrado se realiza en modo de usuario, todos los paquetes, incluidos los que se filtrarán, se copian del kernel al espacio de usuario. Ese intérprete también se puede utilizar al leer un archivo que contiene paquetes capturados con pcap.
Otro intérprete de modo de usuario es uBPF, que admite JIT y eBPF. Su código se ha reutilizado para proporcionar compatibilidad con eBPF en sistemas que no son Linux. [13] El "eBPF en Windows" de Microsoft se basa en uBPF y el verificador formal PREVAIL. [14]
Programación
El BPF clásico generalmente lo emite un programa a partir de una regla textual de muy alto nivel que describe el patrón que debe coincidir. Una de esas representaciones se encuentra en libpcap. [15] Classic BPF y eBPF también se pueden escribir directamente como código de máquina o utilizando un lenguaje ensamblador para una representación textual. Los ensambladores notables incluyen la bpf_asm
herramienta del kernel de Linux (cBPF), bpfc
(cBPF) y el ubpf
ensamblador (eBPF). El bpftool
comando también puede actuar como desensamblador para ambos tipos de BPF. Los lenguajes ensambladores no son necesariamente compatibles entre sí.
El código de bytes eBPF se ha convertido recientemente en un objetivo de los lenguajes de nivel superior. LLVM agregó soporte para eBPF en 2014, y GCC siguió en 2019. Ambos conjuntos de herramientas permiten compilar C y otros lenguajes compatibles para eBPF. También se puede compilar un subconjunto de P4 en eBPF utilizando BCC, un kit de compilación basado en LLVM. [dieciséis]
Historia
El artículo original fue escrito por Steven McCanne y Van Jacobson en 1992 mientras estaban en el Laboratorio Lawrence Berkeley . [1] [17]
En agosto de 2003, SCO Group afirmó públicamente que el kernel de Linux infringía el código Unix del que eran propietarios. [18] Los programadores descubrieron rápidamente que un ejemplo que dieron fue el filtro de paquetes Berkeley, que de hecho SCO nunca tuvo. [19] La SCO no ha explicado ni reconocido el error, pero la acción legal en curso puede eventualmente forzar una respuesta. [20]
Preocupaciones de seguridad
El ataque Spectre puede aprovechar el compilador eBPF JIT del kernel de Linux para extraer datos de otros procesos del kernel y permitir que el espacio del usuario los lea. [21]
Ver también
- Capa de enlace de datos
Referencias
- ^ a b McCanne, Steven; Jacobson, Van (19 de diciembre de 1992). "El filtro de paquetes BSD: una nueva arquitectura para la captura de paquetes a nivel de usuario" (PDF) .
- ^ "Microsoft adopta la superherramienta eBPF del kernel de Linux, la amplía para Windows" . El registro . 2011-05-11.
- ^ "bpf (4) Filtro de paquetes Berkeley" . FreeBSD . 2010-06-15.
- ^ Watson, Robert NM; Perón, Christian SJ (9 de marzo de 2007). "BPF de copia cero" (PDF) .
- ^ "Linux kernel 3.18, sección 1.3. Bpf () syscall para programas de máquina virtual eBFP" . kernelnewbies.org . 7 de diciembre de 2014 . Consultado el 6 de septiembre de 2019 .
- ^ Jonathan Corbet (24 de septiembre de 2014). "API de llamada al sistema BPF, versión 14" . LWN.net . Consultado el 19 de enero de 2015 .
- ^ Jonathan Corbet (2 de julio de 2014). "Ampliación de BPF ampliado" . LWN.net . Consultado el 19 de enero de 2015 .
- ^ "Linux kernel 3.19, sección 11. Redes" . kernelnewbies.org . 8 de febrero de 2015 . Consultado el 13 de febrero de 2015 .
- ^ Jonathan Corbet (10 de diciembre de 2014). "Adjuntar programas eBPF a sockets" . LWN.net . Consultado el 13 de febrero de 2015 .
- ^ "Linux kernel 4.1, Sección 11. Redes" . kernelnewbies.org . 21 de junio 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 . 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 . Consultado el 18 de diciembre de 2019 .
- ^ "genérico-ebpf / genérico-ebpf" . GitHub .
- ^ "microsoft / ebpf-for-windows: implementación de eBPF que se ejecuta en la parte superior de Windows" . GitHub . Microsoft. 11 de mayo de 2021.
- ^ "Sintaxis BPF" . biot.com .
- ^ "Sumérjase en BPF: una lista de material de lectura" . qmonnet.github.io .
- ^ 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 .
- ^ "Actualización de SCOsource" . 15 Copia ofuscada. Archivado desde el original el 25 de agosto de 2003 . Consultado el 5 de septiembre de 2019 .
- ^ Bruce Perens . "Análisis de la presentación de diapositivas de Las Vegas de SCO" . Archivado desde el original el 17 de febrero de 2009.
- ^ Moglen, Eben (24 de noviembre de 2003). "OCS: sin miedo y sin investigación" . Sistema operativo GNU . La Fundación del Software Libre . Consultado el 5 de septiembre de 2019 .
- ^ "Lectura de memoria privilegiada con un canal lateral" . Equipo de Project Zero en Google . 3 de enero de 2018 . Consultado el 20 de enero de 2018 .
Otras lecturas
- McCanne, Steven; Jacobson, Van (19 de diciembre de 1992). "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
- eBPF.io - Introducción, tutoriales y recursos comunitarios
- bpfc, un compilador Berkeley Packet Filter, desensamblador Linux BPF JIT (parte de netsniff-ng)
- Documentación de BPF , para el kernel de Linux
- Documentación de filtro de Linux , para formatos de código de bytes cBPF y eBPF
- ebpf-para-windows en GitHub