首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为ebtables编写自定义模块?

如何为ebtables编写自定义模块?
EN

Stack Overflow用户
提问于 2012-02-16 22:32:53
回答 2查看 3.4K关注 0票数 4

基本上,我想编写一个内核模块,为ebtables添加一个可能的过滤器。然后我需要告诉ebtables在我设置的桥上使用我的过滤器。

我需要编写自己的模块的原因是,我想在连续的包之间引入延迟(出于某些测试原因)。为了演示,我的网络最初的流量如下所示:

代码语言:javascript
复制
+++-----------------+++-----------------+++-----------------+++-----------------

其中+表示包的流量,-表示线路上没有包。我想在两者之间架一座桥,这样数据包的模式就会变成这样:

代码语言:javascript
复制
+----+----+---------+----+----+---------+----+----+---------+----+----+---------

这意味着我将确保每个包到达之间会有一定的延迟。

现在我已经编写了以下简单的代码,基本上取自linux-source/net/bridge/netfilter/ebt_ip.c:

代码语言:javascript
复制
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);
}

我成功地加载了模块。但就好像它不在那里一样。我没有得到matchcheck函数中的日志,所以桥显然没有考虑我的过滤器。我做错了什么?

我已经尝试了许多组合,首先加载我的过滤器,首先设置桥或首先设置ebtables规则,但它们都没有改变任何东西。

另外,这座桥本身也能用。我确信ebtables也是有效的,因为如果我添加了一个删除包的策略,我不会在最终的计算机上收到它们。我不明白的是如何让ebtables也考虑我的过滤器。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-02-20 14:16:08

要使用内核模块,您还需要为用户空间程序编写适当的插件,然后插入一个调用它的规则。

如果您没有任何选项,请不要在struct xt_match中指定任何.matchsize参数(相当于指定0)。

票数 1
EN

Stack Overflow用户

发布于 2012-02-23 23:04:46

我让它工作了,虽然不是最优雅的方式,但不管怎样,我把它写在这里,供未来的漫游者使用:

假设你的过滤器名称是:"any“

用户空间插件

您需要在ebtables源之外不可用的标头。因此,获取源代码,然后转到extensions文件夹。在Makefile中,将any添加到EXT_FUNC (即要构建的目标),并编写源文件ebt_any.c,如下所示:

代码语言:javascript
复制
#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知道使用你的过滤器的方式。

注意:这些函数中的一些似乎是不必要的,但是如果你不写它们,你会得到一个"BUG: bad merge“错误。

内核空间模块

内核空间模块更简单:

代码语言:javascript
复制
#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!!

编译模块(相当标准)并安装它以便自动加载。或者,您可以在添加/删除ebtables规则之前/之后自己insmodrmmod模块。

如何让ebtables使用你的过滤器

只需添加一个包含--use-any some_value的规则,就可以了。例如:

代码语言:javascript
复制
ebtables -A FORWARD --use-any 1 -j ACCEPT

注意:--use-any是在用户空间插件的ebt_u_match reg.extra_ops (在数组_any_opts中定义)中给定的option

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9313088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档