BPF Netfilter хуки окружения

Вопрос или проблема

Я пытаюсь создать простую программу BPF, чтобы сбрасывать входящие/исходящие пакеты и принимать только пересылаемые пакеты, чтобы её можно было загрузить с помощью bpftool. Я использую Ubuntu 24.04 с версией ядра Linux 6.8. Это моя программа:

#include <linux/bpf.h>

#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include <linux/netfilter.h>

SEC("netfilter") /* подсказка загрузчику BPF, что это программа BPF для netfilter */
int filter(const struct bpf_nf_ctx *ctx) {
  const struct nf_hook_state *state = ctx->state;
  unsigned int routing_decision = state->hook;

  if (routing_decision == NF_INET_LOCAL_IN ||
      routing_decision == NF_INET_LOCAL_OUT)
    return NF_DROP;

  return NF_ACCEPT;
}

char LICENSE[] SEC("license") = "GPL";

Однако, когда я пытаюсь скомпилировать это в объектный файл, я получаю:

clang --target=bpf -O2 -Wall -I/usr/include/x86_64-linux-gnu -c filter.c -o filter.bpf.o
filter.c:8:27: warning: declaration of 'struct bpf_nf_ctx' will not be visible outside of this function [-Wvisibility]
    8 | int filter(const struct bpf_nf_ctx *ctx) {
      |                           ^
filter.c:9:42: error: incomplete definition of type 'struct bpf_nf_ctx'
    9 |   const struct nf_hook_state *state = ctx->state;
      |                                       ~~~^
filter.c:8:27: note: forward declaration of 'struct bpf_nf_ctx'
    8 | int filter(const struct bpf_nf_ctx *ctx) {
      |                           ^
filter.c:10:29: error: incomplete definition of type 'struct bpf_nf_ctx'
   10 |   int routing_decision = ctx->state->hook;
      |                          ~~~^
filter.c:8:27: note: forward declaration of 'struct bpf_nf_ctx'
    8 | int filter(const struct bpf_nf_ctx *ctx) {
      |                           ^
1 warning and 2 errors generated.

После того, как я понял, что struct bpf_nf_ctx определен в nf_bpf_link.h, я добавил необходимые заголовки (#include <net/netfilter/nf_bpf_link.h>, когда полный путь /usr/src/linux-headers-6.8.0-48/include/net/netfilter/nf_bpf_link.h) и это был вывод:

clang --target=bpf -O2 -Wall -I/usr/include/x86_64-linux-gnu -I/usr/src/linux-headers-6.8.0-48/include -c filter.c -o filter.bpf.o
In file included from filter.c:1:
In file included from /usr/src/linux-headers-6.8.0-48/include/linux/bpf.h:8:
In file included from /usr/src/linux-headers-6.8.0-48/include/uapi/linux/filter.h:9:
/usr/src/linux-headers-6.8.0-48/include/linux/compiler.h:251:10: fatal error: 'asm/rwonce.h' file not found
  251 | #include <asm/rwonce.h>
      |          ^~~~~~~~~~~~~~
1 error generated.
make: *** [Makefile:7: all] Error 1

Как правильно настроить свою среду для компиляции программы BPF с использованием хуков netfilter?

Ответ или решение

Настройка окружения для компиляции BPF программы с использованием хуков netfilter

Введение

Преобразование сетевых пакетов в Linux с помощью Berkeley Packet Filter (BPF) — это мощный инструмент, позволяющий разработчикам управлять трафиком на уровне ядра. В данном контексте, вопрос включал создание простой программы BPF для управления входящими и исходящими пакетами с использованием хуков netfilter. Рассмотрим, как правильно настроить окружение для компиляции такую BPF программу на системе Ubuntu 24.04 с ядром Linux версии 6.8.

Проблема с компиляцией

Первая проблема, с которой вы столкнулись, заключалась в том, что компилятор выводил несколько ошибок, связанных с недостаточной видимостью структуры bpf_nf_ctx. В частности, это связано с тем, что эта структура определена в заголовочном файле nf_bpf_link.h, который не был включен в ваши исходные файлы.

Следующая проблема возникла уже после добавления необходимых заголовочных файлов, когда компилятор не смог найти файл asm/rwonce.h. Это указывает на проблему с путями к заголовочным файлам или самими заголовочными файлами в вашей системе.

Шаги по настройке окружения

  1. Убедитесь в наличии необходимых заголовочных файлов:
    Для успешной компиляции BPF программ, вам понадобятся заголовочные файлы, относящиеся к вашей версии ядра Linux и специализированные для BPF.
    Установите зависимости, если они ещё не установлены:

    sudo apt update
    sudo apt install linux-headers-$(uname -r) clang llvm libelf-dev

    Замечание: Пакет linux-headers-$(uname -r) должен соответствовать вашему текущему ядру.

  2. Настройка путей к заголовочным файлам:
    Используйте правильные пути для #include. Наведитесь на директорию, в которой находятся заголовочные файлы для вашего ядра и убедитесь, что ваш код включает нужные заголовки:

    #include <linux/bpf.h>
    #include <linux/netfilter.h>
    #include <net/netfilter/nf_bpf_link.h>
    #include <bpf/bpf_helpers.h>
  3. Компилируйте с правильными флагами:
    Команда компиляции должна быть подобным образом настроена для обработки BPF кода:

    clang --target=bpf -O2 -I/usr/src/linux-headers-$(uname -r)/include -c filter.c -o filter.bpf.o

    При этом убедитесь, что даже если компилятор выдает предупреждения, ошибки должны быть устранены. В частности, проверьте наличие rwonce.h, и если файл не найден, попробуйте переустановить необходимые пакеты ядра.

  4. Проверка вывода:
    После успешной компиляции, вы получите объектный файл filter.bpf.o, который затем можно загрузить с использованием bpftool:

    bpftool prog load filter.bpf.o /sys/fs/bpf/filter
  5. Загрузка и работа с программой:
    Убедитесь, что вы правильно загружаете BPF программу в нужное место и прикрепляете её к нужным хукам в рамках netfilter. Пример команды для привязки вашей программы к хуку:

    bpftool net filter add hook ingress dev eth0

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...