Пакетный фильтр Беркли - Berkeley Packet Filter

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

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

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

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

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

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

Фильтрация

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

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

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

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

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

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

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

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

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

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

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

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

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

История

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

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

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

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

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

Рекомендации

  1. ^ а б Макканн, Стивен; Якобсон, Ван (1992-12-19). «Фильтр пакетов BSD: новая архитектура для захвата пакетов на уровне пользователя» (PDF).
  2. ^ "bpf (4) Пакетный фильтр Беркли". FreeBSD. 2010-06-15.
  3. ^ Уотсон, Роберт Н. М .; Перон, Кристиан С. Дж. (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. Получено 2019-12-18.
  12. ^ "generic-ebpf / generic-ebpf". GitHub.
  13. ^ "Синтаксис BPF". biot.com.
  14. ^ «Погрузитесь в БНФ: список материалов для чтения». qmonnet.github.io.
  15. ^ Макканн, Стивен; Якобсон, Ван (январь 1993 г.). «Фильтр пакетов BSD: новая архитектура для захвата пакетов на уровне пользователя». USENIX.
  16. ^ "SCOsource update". 15 Запутанное копирование. Архивировано из оригинал 25 августа 2003 г.. Получено 5 сентября, 2019.
  17. ^ Брюс Перенс. «Анализ слайд-шоу ШОС в Лас-Вегасе». Архивировано из оригинал 17 февраля 2009 г.
  18. ^ Моглен, Эбен (24 ноября 2003 г.). «ШОС: без страха и без исследований». Операционная система GNU. Фонд свободного программного обеспечения. Получено 5 сентября, 2019.
  19. ^ «Чтение привилегированной памяти с побочным каналом». Команда Project Zero в Google. 3 января 2018 г.. Получено 20 января, 2018.

внешняя ссылка