Pregunta

Básicamente, quiero escribir un módulo de núcleo que agrega un posible filtro a EBTables. Entonces necesito decirle a EBTables que use mi filtro en un puente que he configurado.

La razón por la que necesito escribir mi propio módulo es que quiero introducir un retraso entre paquetes consecutivos (por algún motivo de prueba). Para demostrar, mi red originalmente tiene un tráfico como este:

+++-----------------+++-----------------+++-----------------+++-----------------

dónde + muestra el tráfico de un paquete y - significa que ningún paquete en la línea. Quiero poner un puente en el medio para que el patrón de los paquetes cambie a esto:

+----+----+---------+----+----+---------+----+----+---------+----+----+---------

Esto significa que me aseguraría de que habría una cierta cantidad de retraso entre la llegada de cada paquete.

Ahora he escrito el siguiente código simple que básicamente tomé de 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);
}

Cargo con éxito el módulo. Pero es como si no estuviera allí. No estoy obteniendo los registros dentro match y check Funciones para que el puente claramente no esté considerando mi filtro. ¿Qué estoy haciendo mal?

He probado muchas combinaciones de cargar mi filtro primero, configurar primero el puente o configurar las reglas de Ebtables primero, pero ninguna de ellas cambia nada.

Ps El puente en sí funciona. Estoy seguro de que EBTables también está vigente porque si agrego una política para soltar paquetes, no los recibo en la computadora final. Lo que no puedo entender es cómo decirle a EBTables que también considere mi filtro.

¿Fue útil?

Solución

Para usar un módulo de núcleo, también debe escribir un complemento apropiado para el programa UserSapace, y luego, inserte una regla que lo invoque.

Si no tiene ninguna opción, no especifique ninguna .matchsize parámetro en struct xt_match (igual a especificar 0).

Otros consejos

Hice que esto funcionara, no de la manera más elegante, pero de todos modos, lo estoy escribiendo aquí para un futuro vagabundo:

Digamos que el nombre de su filtro es: "Cualquiera"

Complemento del espacio de usuario

Necesita encabezados que no estén disponibles fuera de la fuente de EBTables. Entonces, obtenga el código fuente y vaya a la carpeta Extensions. En el makfile, agregar any a EXT_FUNC (que son los objetivos a construir) y escriba el archivo de origen ebt_any.c Como lo siguiente:

#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);
}

Nota: Si tiene datos que van del espacio de usuario al espacio del núcleo, escriba algo en lugar de struct whatever. Lo he comentado porque no estoy usando nada.

Nota: Incluso si su programa no requiere una opción (como la mía que se suponía que coincide con todo), debe dar una opción de todos modos porque así es como EBTables sabe usar su filtro.

Nota: Algunas de estas funciones parecen innecesarias, pero si no las escribes, obtienes un error de "error: mala fusión".

Módulo de espacio de núcleo

El módulo del espacio de kernel es más simple:

#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");
}

Nota: si utiliza struct whatever En el espacio de usuario, debe usar lo mismo en el espacio del núcleo.

Nota: A diferencia del complemento de espacio de usuario que usa encabezados/funciones EBTables, ¡el módulo del núcleo usa xtables en su lugar!

Compile el módulo (bastante estándar) e instálelo para carga automática. Alternativamente, puedes insmod y rmmod El módulo usted mismo antes de agregar/después de eliminar las reglas de EBTables.

Cómo hacer que los ebtables usen su filtro

Solo agregue una regla que contenga --use-any some_value Y estás bien. Por ejemplo:

ebtables -A FORWARD --use-any 1 -j ACCEPT

Nota: este --use-any es el option que fue dado en ebt_u_match reg.extra_ops (que se definió en la matriz _any_opts) en el complemento de espacio de usuario.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top