Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

Фильтр Berkeley Packet ( BPF ) представляет собой технологию , используемую в некоторых компьютерных операционных систем для программ , которые необходимо, помимо прочего, анализа сетевого трафика. Он обеспечивает необработанный интерфейс для уровней звена данных , позволяя отправлять и получать необработанные пакеты канального уровня. [1] Он доступен в большинстве Unix-подобных операционных систем. Кроме того, если драйвер сетевого интерфейса поддерживает неразборчивый режим , он позволяет перевести интерфейс в этот режим, чтобы можно было получать все пакеты в сети , даже те, которые предназначены для других хостов.

BPF поддерживает фильтрацию пакетов, позволяя процессу пользовательского пространства предоставлять программу фильтрации, которая указывает, какие пакеты он хочет получить. Например, процессу tcpdump может потребоваться получать только пакеты, которые инициируют TCP-соединение. BPF возвращает только пакеты, прошедшие фильтр, предоставляемый процессом. Это позволяет избежать копирования нежелательных пакетов из ядра операционной системы в процесс, что значительно повышает производительность.

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

Необработанный интерфейс [ править ]

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

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

Фильтрация [ править ]

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

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

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

Расширения и оптимизации [ править ]

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

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

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

Начиная с версии 3.18, ядро ​​Linux включает расширенную виртуальную машину BPF с десятью 64-битными регистрами, называемую расширенным BPF ( eBPF ). Его можно использовать не для сетевых целей, например, для прикрепления программ eBPF к различным точкам трассировки . [4] [5] [6] Так как ядро версии 3.19, фильтры eBPF может быть присоединены к разъемам , [7] [8] , и, так как ядра версии 4.1, для управления трафиком классификаторов для входа и выхода сетевого канала передачи данных. [9] [10] Исходная и устаревшая версия была задним числом переименована в классический BPF ( cBPF). В настоящее время ядро ​​Linux запускает только eBPF, а загруженный байт-код cBPF прозрачно транслируется в представление eBPF в ядре перед выполнением программы. [11] Весь байт-код проверяется перед запуском для предотвращения атак типа «отказ в обслуживании». До Linux 5.3 верификатор запрещал использование циклов.

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

Другой интерпретатор пользовательского режима - uBPF, который поддерживает JIT и eBPF. Его код был повторно использован для обеспечения поддержки eBPF в системах, отличных от Linux. [12]

Программирование [ править ]

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

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

История [ править ]

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

В августе 2003 года SCO Group публично заявила, что ядро ​​Linux нарушает код Unix, которым они владеют. [16] Программисты быстро обнаружили, что одним из примеров, который они привели, был фильтр пакетов Беркли, которым SCO никогда не владела. [17] SCO не объяснила и не признала ошибку, но продолжающийся судебный процесс может в конечном итоге привести к ответу. [18]

Проблемы безопасности [ править ]

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

См. Также [ править ]

  • Уровень канала передачи данных

Ссылки [ править ]

  1. ^ а б Макканн, Стивен; Якобсон, Ван (1992-12-19). «Фильтр пакетов BSD: новая архитектура для захвата пакетов на уровне пользователя» (PDF) .
  2. ^ "bpf (4) Пакетный фильтр Беркли" . FreeBSD . 2010-06-15.
  3. ^ Уотсон, Роберт Н.М.; Перон, Кристиан SJ (2007-03-09). "Zero-Copy BPF" (PDF) .
  4. ^ "Ядро Linux 3.18, раздел 1.3. Системный вызов bpf () для программ виртуальных машин eBFP" . kernelnewbies.org . 7 декабря 2014 . Проверено 6 сентября 2019 года .
  5. Джонатан Корбет (24 сентября 2014 г.). «API системного вызова BPF, версия 14» . LWN.net . Проверено 19 января 2015 года .
  6. Джонатан Корбет (2 июля 2014 г.). «Расширение расширенного БНФ» . LWN.net . Проверено 19 января 2015 года .
  7. ^ «Ядро Linux 3.19, раздел 11. Сеть» . kernelnewbies.org . 8 февраля 2015 года . Проверено 13 февраля 2015 года .
  8. Джонатан Корбет (10 декабря 2014 г.). «Присоединение программ eBPF к сокетам» . LWN.net . Проверено 13 февраля 2015 года .
  9. ^ «Ядро Linux 4.1, раздел 11. Сеть» . kernelnewbies.org . 21 июня 2015 года . Проверено 17 октября 2015 года .
  10. ^ "Справочное руководство по BPF и XDP" . cilium.readthedocs.io . 24 апреля 2017 года . Проверено 23 апреля 2018 года .
  11. ^ "Справочное руководство по BPF и XDP - документация Cilium 1.6.5" . docs.cilium.io . Проверено 18 декабря 2019 .
  12. ^ "generic-ebpf / generic-ebpf" . GitHub .
  13. ^ "Синтаксис BPF" . biot.com .
  14. ^ «Погрузитесь в BPF: список материалов для чтения» . qmonnet.github.io .
  15. ^ Макканн, Стивен; Якобсон, Ван (январь 1993 г.). «Фильтр пакетов BSD: новая архитектура для захвата пакетов на уровне пользователя» . USENIX .
  16. ^ "Обновление SCOsource" . 15 Запутанное копирование. Архивировано из оригинального 25 августа 2003 года . Проверено 5 сентября 2019 года .
  17. ^ Брюс Перенс . «Анализ слайд-шоу ШОС в Лас-Вегасе» . Архивировано из оригинального 17 февраля 2009 года.
  18. ^ Моглен, Эбен (24 ноября 2003). «ШОС: без страха и без исследований» . Операционная система GNU . Фонд свободного программного обеспечения . Проверено 5 сентября 2019 года .
  19. ^ "Чтение привилегированной памяти с побочным каналом" . Команда Project Zero в Google . 3 января 2018 . Проверено 20 января 2018 года .

Внешние ссылки [ править ]

  • Макканн, Стивен; Якобсон, Ван (1992-12-19). «Фильтр пакетов BSD: новая архитектура для захвата пакетов на уровне пользователя» (PDF) .
  • bpf(4) -  FreeBSD Kernel Interfaces Manual - пример обычного BPF
  • eBPF.io - Введение, учебные пособия и ресурсы сообщества
  • bpfc, компилятор Berkeley Packet Filter, дизассемблер Linux BPF JIT (часть netsniff-ng)
  • Документация BPF для ядра Linux
  • Документация по фильтрам Linux для форматов байт-кода cBPF и eBPF