Как написать собственный модуль для ebtables? - PullRequest
4 голосов
/ 16 февраля 2012

По сути, я хочу написать модуль ядра, который добавляет возможный фильтр в 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(&reg);
}

void cleanup_module(void)
{
    xt_unregister_match(&reg);
}

Я успешно загрузил модуль. Но как будто его там нет. Я не получаю журналы внутри функций match и check, поэтому мост явно не учитывает мой фильтр. Что я делаю не так?

Я пробовал много комбинаций сначала загружать свой фильтр, сначала устанавливать мост или сначала устанавливать правила ebtables, но ни одно из них ничего не меняет.

P.S. Сам мост работает. Я уверен, что ebtables также действует, потому что, если я добавлю политику для удаления пакетов, я не получу их на конечном компьютере. Я не могу понять, как заставить ebtables также учитывать мой фильтр.

Ответы [ 2 ]

7 голосов
/ 23 февраля 2012

У меня это работает, не самым элегантным образом, но в любом случае, я пишу это здесь для будущего странника:

Допустим, имя вашего фильтра: "any"

Плагин пользовательского пространства

Вам нужны заголовки, которые недоступны вне источника 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);
}

Примечание: ifу вас есть данные, идущие из пространства пользователя в пространство ядра, напишите что-нибудь вместо struct whatever.Я закомментировал это, потому что я ничего не использую.

Примечание: , даже если вашей программе не требуется опция (например, моя, которая должна была соответствовать всем), вам нужнов любом случае дать опцию, потому что ebtables знает, как использовать ваш фильтр.

Примечание: некоторые из этих функций кажутся ненужными, но если вы их не напишите, вы получите «BUG»: ошибка слияния ".

Модуль пространства ядра

Модуль пространства ядра проще:

#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(&reg);
        printk("Bridge initializing...done!\n");
        return ret;
}

void cleanup_module(void)
{
        printk("Bridge exiting...\n");
        xt_unregister_match(&reg);
        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

Примечание: this --use-any - это option, заданный в ebt_u_match reg.extra_ops (который был определен в массиве _any_opts) в пространстве пользователяплагин.

1 голос
/ 20 февраля 2012

Чтобы использовать модуль ядра, вам также необходимо написать соответствующий плагин для программы userpace, а затем вставить правило, вызывающее его.

Если у вас нет опций, не указывайте .matchsize параметр в struct xt_match (равен заданию 0).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...