【问题标题】:How to write custom module for ebtables?如何为 ebtables 编写自定义模块?
【发布时间】:2012-03-07 22:59:17
【问题描述】:

基本上,我想编写一个内核模块,为 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);
}

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

我尝试了很多组合,包括先加载过滤器、先设置网桥或先设置 ebtables 规则,但没有一个能改变任何东西。

附:这座桥本身就可以工作。我确信 ebtables 也有效,因为如果我添加一个丢弃包的策略,我不会在最终计算机上收到它们。我想不通的是如何告诉 ebtables 也考虑我的过滤器。

【问题讨论】:

    标签: linux kernel iptables netfilter ebtables


    【解决方案1】:

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

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

    【讨论】:

    • 非常感谢!我正在寻找如何编写用户空间程序,但是使用 ebtables,我能找到的只有this link,它已经完全过时了。存在很多带有 iptables 的东西,但我猜这与我需要的不同。你能指导我找到一个有用的链接或一段我可以阅读并尝试解决这个问题的代码吗?
    • 也许你先在 iptables 上阅读 “Writing Netfilter Modules”(免费 pdf)会得到更好的结果,一旦摄入了足够量的咖啡,就可以返回电子表格。您链接的 ebt howto 页面从快速开始看起来很准确,但请记住,ebtables 是旧 iptables 的一个分支。
    • 我照你说的做了。我阅读了电子书,实现了模块和用户共享对象。我将匹配命名为“any”,将 xt_any.ko 放在可加载的位置(也运行 depmod),将 libxt_any.so 放在 /lib/xtables 中,根据那本书,一切都很好。现在,无论我搜索多少,我都找不到告诉 ebtables 使用我的匹配功能的命令。你有什么想法吗?
    • ebtables 手册页说匹配扩展是自动加载的“所以不需要像 iptables 中需要的 -m”。好的,没有 -m,但无论我尝试什么组合,ebtables 都没有使用我的“任何”匹配扩展!
    • 尝试将它们命名为 ebt_any.ko 和 libebt_any.so(放入 /lib/ebtables)无济于事
    【解决方案2】:

    我得到了这个工作,不是以最优雅的方式,但无论如何,我在这里为未来的流浪者写它:

    假设您的过滤器名称是:“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);
    }
    

    注意:如果你有从用户空间到内核空间的数据,写一些东西而不是struct whatever。我已将其注释掉,因为我没有使用任何东西。

    注意:即使您的程序不需要选项(例如我的应该匹配所有内容),您仍然需要提供选项,因为 ebtables 知道如何使用您的过滤器.

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

    内核空间模块

    内核空间模块更简单:

    #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 的规则即可。例如:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-10
      • 2021-10-29
      • 1970-01-01
      • 1970-01-01
      • 2019-02-10
      • 2019-07-28
      • 1970-01-01
      相关资源
      最近更新 更多