Как написать пользовательский модуль для eBtables?
Вопрос
По сути, я хочу написать модуль ядра, который добавляет возможный фильтр в ebtables. Тогда мне нужно сказать, что ebtables использовать мой фильтр на мосту, который я настроил.
Причина, по которой мне нужно написать свой собственный модуль, заключается в том, что я хочу ввести задержку между последовательными пакетами (по какой -то причине тестирования). Чтобы продемонстрировать, моя сеть изначально имеет такой трафик, как это:
+++-----------------+++-----------------+++-----------------+++-----------------
куда +
показывает движение пакета и -
не означает отсутствие пакета на линии. Я хочу поставить мост между ними, чтобы схема пакетов изменилась на это:
+----+----+---------+----+----+---------+----+----+---------+----+----+---------
Это означает, что я бы позаботился о том, чтобы между прибытием каждого пакета будет определенное количество задержки.
Теперь я написал следующий простой код, который я в основном взял из Linux-Source/Net/Bridge/Netfilter/ebt_ip.c:
static bool match(const struct sk_buff *skb, const struct xt_match_param *par)
{
printk(KERN_INFO"match called\n");
return true; // match everything!
}
static bool check(const struct xt_mtchk_param *par)
{
printk(KERN_INFO"check called\n");
return true; // pass everything!
}
static struct xt_match reg __read_mostly = {
.name = "any", // I made this up, but I tried also putting ip for example which didn't change anything.
.revision = 0,
.family = NFPROTO_BRIDGE,
.match = match,
.checkentry = check,
.matchsize = XT_ALIGN(4), // don't know what this is, so I just gave it an `int`
.me = THIS_MODULE
};
int init_module(void)
{
return xt_register_match(®);
}
void cleanup_module(void)
{
xt_unregister_match(®);
}
Я успешно загружаю модуль. Но это как если бы его не было. Я не получаю журналы внутри match
а также check
Функции, поэтому мост явно не рассматривает мой фильтр. Что я делаю не так?
Я сначала пробовал много комбинаций загрузки моего фильтра, сначала настройка моста или сначала установив правила ebtables, но ни один из них ничего не меняет.
PS сам мост работает. Я уверен, что eBtables также действует, потому что, если я добавлю политику для сброса пакетов, я не получаю их на конечном компьютере. Что я не могу понять, так это то, как сказать, что ebtables также рассмотреть мой фильтр.
Решение
Чтобы использовать модуль ядра, вам также необходимо написать подходящий плагин для программы пользователя, а затем вставить правило, которое его призывает.
Если у вас нет вариантов, не укажите никаких .matchsize
параметр в struct xt_match
(равна указанию 0).
Другие советы
Я получил эту работу, не самым элегантным образом, но в любом случае, я пишу это здесь для будущего странника:
Допустим, ваше имя фильтра: "Любой"
Плагин пользовательского пространства
Вам нужны заголовки, которые недоступны вне источника eBtables. Итак, получите исходный код и перейдите в папку расширений. В Makefile, добавьте any
к EXT_FUNC
(Это целевые показатели, которые должны быть построены) и написать исходный файл ebt_any.c
Как следующее:
#include <stdio.h>
#include <getopt.h>
#include "../include/ebtables_u.h"
/*struct whatever
{
int a;
};*/
static struct option _any_opts[] =
{
{"use-any", required_argument, 0, 0},
{'\0'}
};
static void _any_help(void)
{
printf("any match options: nothing!\n");
}
static void _any_init(struct ebt_entry_match *match)
{
printf("any_init\n");
}
static void _any_check(const struct ebt_u_entry *entry, const struct ebt_entry_match *match, const char *name,
unsigned int hookmask, unsigned int time)
{
printf("any_check\n");
}
static int _any_parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, unsigned int *flags, struct ebt_entry_match **match)
{
printf("any_parse: %d\n", c);
if (c == 0)
return 1;
return 0; // return true for anything
}
static int _any_compare(const struct ebt_entry_match *m1, const struct ebt_entry_match *m2)
{
/* struct whatever *w1 = (struct whatever *)m1->data;
struct whatever *w2 = (struct whatever *)m2->data;
if (w1->a != w2->a)
return 0;*/
return 1;
}
static void _any_print(const struct ebt_u_entry *entry, const struct ebt_entry_match *match)
{
printf("any_print");
}
static struct ebt_u_match _reg = {
.name = "any",
// .size = sizeof(struct whatever),
.help = _any_help,
.init = _any_init,
.parse = _any_parse,
.final_check = _any_check,
.print = _any_print,
.compare = _any_compare,
.extra_ops = _any_opts,
};
void _init(void)
{
ebt_register_match(&_reg);
}
Примечание: Если у вас есть данные, переходящие от пространства пользователя в пространство ядра, напишите что-нибудь вместо struct whatever
. Анкет Я прокомментировал это, потому что я ничего не использую.
Примечание: Даже если вашей программе не требуется вариант (например, моя, которая должна была соответствовать всем), вам в любом случае необходимо дать опцию, потому что это то, как ebtables знает, чтобы использовать ваш фильтр.
Примечание: Некоторые из этих функций кажутся ненужными, но если вы их не пишете, вы получите ошибку «ошибка: плохое слияние».
Модуль пространства ядра
Модуль пространства ядра проще:
#include <linux/netfilter/x_tables.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Shahbaz Youssefi");
MODULE_ALIAS("ebt_any");
/*struct whatever
{
int a;
};*/
static bool match(const struct sk_buff *skb, const struct xt_match_param *par)
{
printk(KERN_INFO"Matching\n");
return true;
}
static bool check(const struct xt_mtchk_param *par)
{
printk(KERN_INFO"Checking\n");
return true;
}
static struct xt_match reg __read_mostly = {
.name = "any",
.match = match,
// .matchsize = sizeof(struct whatever),
.checkentry = check,
.me = THIS_MODULE
};
int init_module(void)
{
int ret = 0;
printk("Bridge initializing...\n");
ret = xt_register_match(®);
printk("Bridge initializing...done!\n");
return ret;
}
void cleanup_module(void)
{
printk("Bridge exiting...\n");
xt_unregister_match(®);
printk("Bridge exiting...done!\n");
}
Примечание: Если вы используете struct whatever
В пользовательском пространстве вы должны использовать то же самое в пространстве ядра.
Примечание: В отличие от плагина пользовательского пространства, который использует заголовки/функции EBTABLES, модуль ядра использует xtables вместо этого !!
Составьте модуль (довольно стандартный) и установите его для автоматической загрузки. В качестве альтернативы вы можете insmod
а также rmmod
Модуль самостоятельно перед добавлением/после удаления правил ebtables.
Как заставить eBtables использовать ваш фильтр
Просто добавьте правило, которое содержит --use-any some_value
И ты в порядке. Например:
ebtables -A FORWARD --use-any 1 -j ACCEPT
Примечание: это --use-any
это option
это было дано в ebt_u_match reg.extra_ops
(который был определен в массиве _any_opts
) в плагине пространства пользователя.