Фильтр пакетов Беркли

Интерфейс к уровням канала передачи данных в Unix-подобной системе
Фильтр пакетов Беркли
Разработчик(и)Стивен МакКейн, Ван Якобсон
Первоначальный выпуск19 декабря 1992 г .; 32 года назад ( 1992-12-19 )
Операционная системаНесколько

Berkeley Packet Filter ( BPF ; также BSD Packet Filter , классический BPF или cBPF ) — сетевой фильтр и фильтр пакетов , который позволяет захватывать и фильтровать пакеты компьютерной сети на уровне операционной системы . Он предоставляет необработанный интерфейс для уровней канала передачи данных , позволяя отправлять и получать необработанные пакеты уровня канала, [1] и позволяет процессу пользовательского пространства предоставлять программу-фильтр, которая указывает, какие пакеты он хочет получать. Например, процесс tcpdump может захотеть получать только пакеты, которые инициируют TCP-соединение. BPF возвращает только пакеты, которые проходят фильтр, предоставляемый процессом. Это позволяет избежать копирования нежелательных пакетов из ядра операционной системы в процесс, что значительно повышает производительность. Программа-фильтр имеет форму инструкций для виртуальной машины , которые интерпретируются или компилируются в машинный код с помощью механизма JIT и выполняются в ядре.

BPF используется программами, которым необходимо, помимо прочего, анализировать сетевой трафик. Если драйвер сетевого интерфейса поддерживает режим promiscuous , он позволяет перевести интерфейс в этот режим, чтобы можно было получать все пакеты в сети , даже те, которые предназначены для других хостов.

Механизм фильтрации BPF доступен в большинстве операционных систем типа Unix . Иногда BPF используется для обозначения только механизма фильтрации, а не всего интерфейса. Некоторые системы, такие как Linux и Tru64 UNIX , предоставляют необработанный интерфейс к канальному уровню, отличный от необработанного интерфейса BPF, но используют механизмы фильтрации BPF для этого необработанного интерфейса.

Ядро Linux предоставляет расширенную версию механизма фильтрации BPF, называемую eBPF , которая использует механизм JIT и которая используется для фильтрации пакетов, а также для других целей в ядре. eBPF также доступен для Microsoft Windows . [2]

История

Оригинальная статья была написана Стивеном МакКэнном и Ван Якобсоном в 1992 году в лаборатории Лоуренса в Беркли . [1] [3]

BPF предоставляет псевдоустройства , которые можно привязать к сетевому интерфейсу; операции чтения с устройства будут считывать буферы, заполненные пакетами, полученными на сетевом интерфейсе, а операции записи на устройство будут внедрять пакеты на сетевой интерфейс.

В 2007 году Роберт Уотсон и Кристиан Перон добавили расширения буфера нулевого копирования к реализации BPF в операционной системе FreeBSD , [4] что позволило захвату пакетов ядра в обработчике прерываний драйвера устройства записывать данные непосредственно в память пользовательского процесса, чтобы избежать необходимости в двух копиях для всех данных пакета, полученных через устройство BPF. В то время как одна копия остается в пути получения для пользовательских процессов, это сохраняет независимость различных потребителей устройств BPF, а также позволяет упаковывать заголовки в буфер BPF вместо копирования полных данных пакета. [5]

Фильтрация

Возможности фильтрации BPF реализованы как интерпретатор машинного языка для виртуальной машины BPF , 32-битной машины с фиксированной длиной инструкций, одним аккумулятором и одним индексным регистром . Программы на этом языке могут извлекать данные из пакета, выполнять арифметические операции с данными из пакета и сравнивать результаты с константами или с данными в пакете или тестовыми битами в результатах, принимая или отклоняя пакет на основе результатов этих тестов.

BPF часто расширяется за счет «перегрузки» инструкций загрузки (ld) и сохранения (str).

Традиционные Unix-подобные реализации BPF могут использоваться в пользовательском пространстве, несмотря на то, что они написаны для пространства ядра. Это достигается с помощью условий препроцессора .

Расширения и оптимизации

В некоторых проектах используются наборы инструкций BPF или методы выполнения, отличные от оригинальных.

Некоторые платформы, включая FreeBSD , NetBSD и WinPcap , используют JIT -компилятор (Just-in-Time Compiler , JIT) для преобразования инструкций BPF в машинный код с целью повышения производительности. Linux включает в себя JIT-компилятор BPF, который по умолчанию отключен.

Интерпретаторы режима ядра для того же языка виртуальной машины используются в механизмах уровня необработанных данных в других операционных системах, таких как Tru64 Unix , а также для фильтров сокетов в ядре Linux и в механизмах захвата пакетов WinPcap и Npcap .

Реализации

Пользовательский интерпретатор для BPF предоставляется с реализацией libpcap/WinPcap/Npcap API pcap , так что при захвате пакетов в системах без поддержки режима ядра для этого механизма фильтрации пакеты могут быть отфильтрованы в пользовательском режиме; код, использующий API pcap, будет работать в обоих типах систем, хотя в системах, где фильтрация выполняется в пользовательском режиме, все пакеты, включая те, которые будут отфильтрованы, копируются из ядра в пользовательское пространство. Этот интерпретатор также может использоваться при чтении файла, содержащего пакеты, захваченные с помощью pcap.

Другой интерпретатор пользовательского режима — uBPF , который поддерживает JIT и eBPF (без cBPF). Его код был повторно использован для обеспечения поддержки eBPF в системах, отличных от Linux. [6] eBPF от Microsoft на Windows построен на uBPF и формальном верификаторе PREVAIL. [7] rBPF , переписанный на Rust uBPF, используется блокчейн-платформой Solana в качестве механизма выполнения. [8]

Программирование

Классический BPF обычно выдается программой из некоторого очень высокоуровневого текстового правила, описывающего шаблон для сопоставления. Одно из таких представлений находится в libpcap . [9] Классический BPF и eBPF также могут быть записаны либо непосредственно как машинный код , либо с использованием языка ассемблера для текстового представления. Известные ассемблеры включают инструмент ядра Linux bpf_asm(cBPF), bpfc(cBPF) и ubpfассемблер (eBPF). bpftoolКоманда также может действовать как дизассемблер для обеих разновидностей BPF. Языки ассемблера не обязательно совместимы друг с другом.

Байт-код eBPF недавно стал целью языков более высокого уровня. LLVM добавил поддержку eBPF в 2014 году, а GCC последовал за ним в 2019 году. Оба набора инструментов позволяют компилировать C и другие поддерживаемые языки в eBPF. Подмножество P4 также может быть скомпилировано в eBPF с помощью BCC, набора компиляторов на основе LLVM. [10]

Безопасность

Атака Spectre может использовать интерпретатор eBPF ядра Linux или JIT-компилятор для извлечения данных из других процессов ядра. [ 11] Функция усиления JIT в ядре смягчает эту уязвимость. [12]

Китайская группа по компьютерной безопасности Pangu Lab заявила, что АНБ использовало BPF для сокрытия сетевых коммуникаций как часть сложного бэкдора Linux . [13]

eBPF

Начиная с версии 3.18, ядро ​​Linux включает расширенную виртуальную машину BPF с десятью 64-битными регистрами, называемую eBPF . Она может использоваться для несетевых целей, например, для присоединения программ eBPF к различным точкам трассировки . [14] [15] [16] Начиная с версии ядра 3.19, фильтры eBPF могут быть присоединены к сокетам , [17] [18] и, начиная с версии ядра 4.1, к классификаторам управления трафиком для входящего и исходящего сетевого пути данных. [19] [20] Первоначальная и устаревшая версия была ретроактивно переименована в классический BPF ( cBPF ). В настоящее время ядро ​​Linux запускает только eBPF, а загруженный байт-код cBPF прозрачно транслируется в представление eBPF в ядре перед выполнением программы. [21] Весь байт-код проверяется перед запуском, чтобы предотвратить атаки типа «отказ в обслуживании». До Linux 5.3 верификатор запрещал использование циклов, чтобы предотвратить потенциально неограниченное время выполнения; циклы с ограниченным временем выполнения теперь разрешены в более поздних ядрах. [22]

Смотрите также

Ссылки

  1. ^ ab McCanne, Steven; Jacobson, Van (1992-12-19). "Фильтр пакетов BSD: новая архитектура для захвата пакетов на уровне пользователя" (PDF) . Архивировано (PDF) из оригинала 2009-04-19 . Получено 2009-05-25 .
  2. ^ "Microsoft принимает супер-инструмент eBPF ядра Linux, расширяет его для Windows". The Register . 2021-05-11. Архивировано из оригинала 2021-05-11.
  3. ^ Макканн, Стивен; Якобсон, Ван (январь 1993 г.). «Фильтр пакетов BSD: новая архитектура для захвата пакетов на уровне пользователя». USENIX . Архивировано из оригинала 2020-08-03 . Получено 2014-06-10 .
  4. ^ "bpf(4) Berkeley Packet Filter". FreeBSD . 2010-06-15. Архивировано из оригинала 2020-10-21 . Получено 2014-06-10 .
  5. ^ Уотсон, Роберт НМ; Перон, Кристиан СЖ (2007-03-09). "Zero-Copy BPF" (PDF) . Архивировано (PDF) из оригинала 2008-05-16 . Получено 2008-07-29 .
  6. ^ "generic-ebpf/generic-ebpf". GitHub . 28 апреля 2022 г. Архивировано из оригинала 27 сентября 2020 г. Получено 4 августа 2020 г.
  7. ^ "microsoft/ebpf-for-windows: реализация eBPF, работающая поверх Windows". GitHub . Microsoft. 11 мая 2021 г. Архивировано из оригинала 11 мая 2021 г. Получено 11 мая 2021 г.
  8. ^ "Обзор | Solana Docs". Архивировано из оригинала 2022-01-31 . Получено 2022-01-31 .
  9. ^ "BPF syntax". biot.com . Архивировано из оригинала 2020-08-14 . Получено 2020-08-03 .
  10. ^ "Погружение в BPF: список материалов для чтения". qmonnet.github.io . Архивировано из оригинала 2019-10-02 . Получено 2020-08-04 .
  11. ^ "Чтение привилегированной памяти с помощью побочного канала". Команда Project Zero в Google . 3 января 2018 г. Архивировано из оригинала 1 октября 2019 г. Получено 20 января 2018 г.
  12. ^ "bpf: introduce BPF_JIT_ALWAYS_ON config". git.kernel.org . Архивировано из оригинала 2020-10-19 . Получено 2021-09-20 .
  13. ^ "Анатомия подозреваемого топового десятилетнего скрытого бэкдора АНБ". The Register . 23 февраля 2022 г. Архивировано из оригинала 23 февраля 2022 г. Получено 24 февраля 2022 г.
  14. ^ "Linux kernel 3.18, Section 1.3. bpf() syscall for eBFP virtual machine programs". kernelnewbies.org . 7 декабря 2014 г. Архивировано из оригинала 25 октября 2019 г. Получено 6 сентября 2019 г.
  15. Jonathan Corbet (24 сентября 2014 г.). "Системный вызов API BPF, версия 14". LWN.net . Архивировано из оригинала 27 декабря 2014 г. . Получено 19 января 2015 г. .
  16. Jonathan Corbet (2 июля 2014 г.). «Расширение расширенного BPF». LWN.net . Архивировано из оригинала 24 апреля 2019 г. Получено 19 января 2015 г.
  17. ^ "Linux kernel 3.19, Section 11. Networking". kernelnewbies.org . 8 февраля 2015 г. Архивировано из оригинала 12 февраля 2015 г. Получено 13 февраля 2015 г.
  18. ^ Джонатан Корбет (10 декабря 2014 г.). «Присоединение программ eBPF к сокетам». LWN.net . Архивировано из оригинала 14 февраля 2015 г. Получено 13 февраля 2015 г.
  19. ^ "Linux kernel 4.1, Section 11. Networking". kernelnewbies.org . 21 июня 2015 г. Архивировано из оригинала 16 октября 2015 г. Получено 17 октября 2015 г.
  20. ^ "BPF and XDP Reference Guide". cilium.readthedocs.io . 24 апреля 2017 г. Архивировано из оригинала 24 апреля 2018 г. Получено 23 апреля 2018 г.
  21. ^ "Справочное руководство по BPF и XDP — документация Cilium 1.6.5". docs.cilium.io . Архивировано из оригинала 2020-09-18 . Получено 2019-12-18 .
  22. ^ "bpf: introduce bounded loops". git.kernel.org . 19 июня 2019 г. Архивировано из оригинала 20 августа 2022 г. Получено 19 августа 2022 г.

Дальнейшее чтение

  • МакКейн, Стивен; Якобсон, Ван (1992-12-19). «Фильтр пакетов BSD: новая архитектура для захвата пакетов на уровне пользователя» (PDF) .
  • bpf(4) –  Руководство по интерфейсам ядра FreeBSD – пример обычного BPF
  • bpfc, компилятор Berkeley Packet Filter, дизассемблер Linux BPF JIT (часть netsniff-ng)
  • Документация BPF для ядра Linux
  • Документация по фильтрам Linux для форматов байт-кода cBPF и eBPF
Получено с "https://en.wikipedia.org/w/index.php?title=Berkeley_Packet_Filter&oldid=1264495197"