Топ питань
Часова шкала
Чат
Перспективи
Berkeley Packet Filter
З Вікіпедії, вільної енциклопедії
Remove ads
BPF (Berkeley Packet Filter), англ. Фільтр пакетів Берклі — технологія операційної системи, що надає інтерфейс для роботи з чистими мережевими кадрами на канальному рівні.[1] Більшість Unix-подібних операційних операційних систем мають підтримку BPF інтерфейсу.
BPF дозволяє процесам з простору користувача додавати до будь якого відкритого сокета фільтр та дозволяти або забороняти проходження певних даних через вибраний сокет. Для прикладу, використовуючи BPF фільтр, tcpdump може отримувати тільки TCP SYNC пакети. Для цього генерується відповідний BPF фільтр, що пропускає тільки потрібний користувачу трафік. Застосування такого фільтру покращує загальну продуктивність системи, оскільки ядро операційної системи не копіює небажаний трафік до буфера у просторі користувача.
Іноді під абревіатурою BPF мають на увазі тільки механізм фільтрації, а не весь інтерфейс BPF. Деякі системи, такі як Linux та Tru64 UNIX, надають інший, відмінний від BPF інтерфейс доступу до "сирих" мережевих кадрів на канальному рівні, залишаючи механізм фільтрації BPF для свого "сирого" інтерфейсу.
Remove ads
"Сирий" інтерфейс
Також, BPF надає псевдо-пристрої (BPF-пристрої), які можуть бути прив'язані до мережевих інтерфейсів; читання з пристрою буде зчитувати буфер отриманих мережевим інтерфейсом пакетів, запис даних у пристрій буде випускати пакети з мережевого інтерфейсу.
В 2007, Роберт Уотсон та Крістіан Перон додали розширення з zero-copy buffer до імплементації BPF у FreeBSD[2], дозволяючи драйверу мережевої карти записувати дані прямо в пам'ять користувацького процесу, для уникнення зайвих копіювань даних. Таким чином, замість двох копіювань (драйвер -> буфер ядра -> пам'ять процесу), відбувається одне копіювання в спільну пам'ять BPF програм у просторі користувача. Дана імплементація зберігає незалежність різних BPF-пристроїв один від одного при використанні спільної пам'яті.[3]
Remove ads
Фільтрація
Узагальнити
Перспектива
Функціонал фільтрації BPF імплементований як інтерпретатор для машинної мови, що виконується віртуальною машиною BPF (розрядність 32-біт, фіксована довжина інструкцій, один акумулятор та один індексний регістр). Програми, написані цією мовою, можуть доступатись до даних пакету, виконувати арифметичні та логічні операції над даними пакета, виконувати порівняння константних значень, результатів обчислень, даних в пакеті, а також приймати рішення щодо пропуску або відкидання пакету.
Функціонал BPF часто розширюється шляхом "перевантаження" інструкцій "load" (ld) та "store" (st).
Традиційні Unix-подібні імплементації BPF можуть використовуватись програмами в просторі користувача. Для цього необхідно використати певні прапорців препроцесора, оскільки в оригіналі BPF був написаний для роботи в просторі ядра.
Розширення та оптимізації
Не всі імплементації BPF однакові з функціональної точки зору. Деякі проекти мають відмінний від оригінальної імплементації набір інструкцій або техніки виконання коду.
Деякі платформи, такі як FreeBSD, NetBSD та WinPcap, використовують JIT компілятори для перетворення BPF інструкцій у машинний код заради збільшення швидкодії. Імплементація в Linux підтримує режим робити з JIT-компілятором, який виключений за замовчуванням.
Інтерпретатори в ядрі ОС можуть використовуватись для різних цілей. В ядрі Tru64 Unix присутній на канальному рівні, та для фільтрації на рівні сокетів у ядрі Linux, WinPcap та Npcap.
З версії ядра 3.18, в Linux з'являється розширена версія віртуальної машини BPF з 10-ю 64-бітних регістрів, названий extended BPF (eBPF, англ. розширений фільтр пакетів Берклі). Він може бути використаний виконання не мережевих задач, наприклад для обробки інформації у точках трасування в ядрі ОС.[4][5][6] У версії ядра 3.19 Linux eBPF фільтри можуть бути закріплені на сокетах,[7][8] а з версії 4.1 - до класифікаторів керування трафіку вхідних та вихідних шляхів даних.[9][10] З поширенням eBPF стало прийнято називати оригінальну версію classic BPF (cBPF, англ. класичний фільтр пакетів Берклі). Поточні версії ядра Linux працюють тільки з eBPF-байт кодом, в той час як cBPF-байт код транслюється у eBPF безпосередньо перед виконанням.[11] Весь байт код, перед завантаженням в ядро проходить перевірку на відповідність певних безпекових параметрів. З версії ядра Linux 5.3, верифікатор дозволяє використання циклів.[12]
Наявна імплементація pcap API (з бібліотек libpcap/WinPcap/Npcap) інтерпретатора BPF для простору користувача, що дозволяє використовувати фільтрувальний функціонал BPF на ОС, що не мають такої підтримки у ядрі ОС. Код, що використовує pcap API, буде працювати на обох системах, проте у випадку відсутності підтримки фільтру на рівні ОС, всі пакети будуть копіюватись з простору ядра до буфера програми у простір користувача. Цей інтерпретатор також може бути використаний для фільтрації пакетів з файлу.
Інтерпретатор uBPF працює у просторі користувача, підтримує JIT-компіляцію та розширення eBPF.[13] uBPF ліг в основу інтерпретатора проєкта generic-eBPF, що використовується у не-Linux системах.[14]
Remove ads
Програмування
Класичний BPF код зазвичай генерується програмою з високорівневого текстового правила, що описує шаблон роботи фільтру. Прикладом такого використання є libpcap.[15] Класичний BPF та eBPF код також може бути згенерований одразу у вигляді машинного коду, або з текстового опису мовою асемблера. Прикладами таких асемблерів в ядрі Linux є bpf_asm (cBPF), bpfc (cBPF), а також ubpf ассемблер (eBPF). Команда bpftool має вбудований функціонал дизассемблера для cBPF та eBPF. Сумісність різних мов асемблера між собою не гарантується.
eBPF-байткод отримує підтримку все більшої кількості високорівневих мов програмування. LLVM отримав підтримку eBPF у 2014, GCC - у 2019. Обидва інструменти дозволяють компіляцію C - коду та інших підтримуваних мов програмування у eBPF-байткод. Підмножина мови програмування P4[en] також може бути скомпільована у eBPF-байткод за допомогою BCC, та LLVM.[16]
Історія
Перша стаття, що описує BPF, була написана робітниками Національної лабораторії ім. Лоуренса в Берклі, Стівеном МакКейном та Ван Якобсоном, у 1992 році.[1][17]
В Серпні 2003 року, SCO Group[en] зробила публічну заяву, що у ядрі Linux присутній код Unix, правами на який вони, SCO Group, володіють.[18] Програмісти швидко дізнались, що як приклад, було наведено BPF, правами на який SCO ніколи не володіла.[19] SCO не давала пояснень та не визнає своєї помилки, проте робота над порушеними юридичними справами може дати відповідь на це питання.[20]
Remove ads
Проблеми безпеки
Атаки типу Spectre можуть використовувати eBPF JIT-компілятор для отримання доступу до даних процесів ядра, що може привести до читання захищених даних процесом з простору користувача.[21]
Див. також
Посилання
Зовнішні посилання
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads