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

редактировать

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

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

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

Содержание

  • 1 Необработанный интерфейс
  • 2 Фильтрация
    • 2.1 Расширения и оптимизации
  • 3 Программирование
  • 4 История
  • 5 Проблемы безопасности
  • 6 См. Также
  • 7 Ссылки
  • 8 Внешние ссылки

Необработанный интерфейс

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

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

Фильтрация

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

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

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

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

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

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

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

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

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

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

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

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

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

История

Исходная статья была написана и Ван Якобсон в 1992 году, находясь в Лаборатории Лоуренса Беркли

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

Проблемы безопасности

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

См. также

Ссылки

Внешние ссылки

Последняя правка сделана 2021-05-12 12:59:51
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте