BPF — Что такое пакетный фильтр Беркли?

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

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

Как работает пакетный фильтр Беркли?

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

Используя SysCalls — т.е. вызывая специальные, оперативные системные функции — Berkeley Filter посылает запросы ядру. Оно проверяет права доступа, прежде чем подтвердить или отклонить запрос. Около 330 SysCalls Linux включают следующие:

  • read — позволяет прочитать файл
  • write — разрешает запись файла
  • open — открывает файлы или устройства
  • close — закрывает файлы или устройства
  • stat — запрашивает состояние файла

Благодаря постоянному развитию, BPF теперь работает как универсальная, виртуальная машина непосредственно в ядре, где происходит вся организация процессов и данных. Благодаря множеству новых функций фильтр известен как Extended BPF — или сокращенно eBPF. Он может безопасно запускать любой прикладной промежуточный язык (байт-код) во время выполнения (компиляция just-in-time) непосредственно в ядре. Extended BPF работает в изолированной среде ядра и поэтому выполняется под защитой. Эта модель среды — известная как «песочница» — помогает снизить риск того, что система окажет негативное влияние на логику ядра.

Примечание

Berkeley Filter может работать как в режиме ядра (максимальный доступ к ресурсам компьютера), так и в режиме пользователя (ограниченный доступ к вычислительным ресурсам).

Преимущества фильтра Беркли

Используя eBPF, вы можете фильтровать пакеты данных и предотвращать замедление производительности компьютера за счет неактуальных данных. Непригодные или ошибочные наборы данных могут быть сразу же отклонены или исправлены. Более того, расширенный BPF обеспечивает повышенную безопасность SysCalls; вы можете легко измерять производительность с помощью системных вызовов или отслеживать процессы.

В 2007 году реализация BPF была дополнена «расширениями буфера нулевой копии». Благодаря этим расширениям драйверы устройств могут сохранять собранные пакеты данных непосредственно в программе без необходимости предварительного копирования данных.

Программирование фильтров с помощью BPF

В режиме пользователя вы можете в любое время определить индивидуальные фильтры для интерфейса Berkeley Filter. Раньше соответствующие коды писались вручную и переводились в байт-код BPF. В настоящее время компилятор LLVM Clang позволяет переводить байт-коды напрямую.

Примеры программ также хранятся в библиотеках ядра, что упрощает процесс определения программ eBPF. Различные справочные функции облегчают работу с фильтрами.

Верификатор eBPF для обеспечения безопасности

Выполнение системных вызовов в ядре всегда связано с определенными рисками безопасности и стабильности. Перед загрузкой системного вызова eBPF он должен пройти ряд проверок:

  1. Во-первых, проверяется, был ли системный вызов завершен и не содержит ли он каких-либо циклов. В противном случае это может привести к аварийному завершению работы ядра. Во время этого процесса проверяется граф потока управления (CFG) программы, чтобы обнаружить недоступные инструкции, которые впоследствии не загружаются.
  2. До и после выполнения инструкции проверяется статус системного вызова eBPF. Это делается для того, чтобы расширенный BPF действовал только в разрешенных областях и не обращался к данным за пределами «песочницы». Однако не каждый путь нужно проверять отдельно. Обычно достаточно подмножества.
  3. Наконец, настраивается тип SysCall. Этот шаг важен для ограничения того, какие функции ядра могут быть вызваны из SysCall и к каким структурам данных можно получить доступ. Таким образом, вы можете использовать системные вызовы, например, для прямого доступа к данным сетевых пакетов.

Типы SysCall обычно обрабатывают четыре функции: куда может быть присоединена программа, какие справочные функции ядра могут быть вызваны, можно ли обращаться к данным сетевых пакетов напрямую или косвенно и какой тип объекта передается в качестве приоритетного в системном вызове.

Следующие типы eBPF SysCall в настоящее время поддерживаются ядром:

  • BPF_PROG_TYPE_SOCKET_FILTER
  • BPF_PROG_TYPE_KPROBE
  • BPF_PROG_TYPE_SCHED_CLS
  • BPF_PROG_TYPE_SCHED_ACT
  • BPF_PROG_TYPE_TRACEPOINT
  • BPF_PROG_TYPE_XDP
  • BPF_PROG_TYPE_PERF_EVENT
  • BPF_PROG_TYPE_CGROUP_SKB
  • BPF_PROG_TYPE_CGROUP_SOCK
  • BPF_PROG_TYPE_LWT_ *
  • BPF_PROG_TYPE_SOCK_OPS
  • BPF_PROG_TYPE_SK_SKB
  • BPF_PROG_CGROUP_DEVICE

Оцените статью
cdelat.ru
Добавить комментарий