How to write a custom module for ebtables?

Basically, I want to write a kernel module that adds a possible filter to ebtables. Then I need to tell ebtables to use my filter on the bridge that I installed.

The reason I need to write my own module is because I want to introduce a delay between consecutive packets (for some testing reason). To demonstrate, my network initially has this traffic:

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

where + shows the packet traffic, and - means the packet is not in the line. I want to establish a bridge between them so that the packet pattern changes to this:

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

This means that I will ensure that there is a certain delay between the arrival of each package.

Now I wrote the following simple code, which I basically took from 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); } 

I successfully load the module. But it’s as if it weren’t. I do not get the logs inside the match and check functions, so the bridge does not explicitly consider my filter. What am I doing wrong?

I tried many combinations of loading my filter first, first installed the bridge or first set the ebtables rules, but none of them changed anything.

PS The bridge itself works. I am sure that ebtables also works, because if I add a policy to remove packages, I do not receive them on the destination computer. I cannot figure out how to say ebtables to view my filter.

+4
source share
2 answers

To use the kernel module, you also need to write the appropriate plugin for the user space program, and then insert the rule that calls it.

If you do not have parameters, do not specify the .matchsize parameter in struct xt_match (equal to job 0).

+1
source

I did not get this work in the most elegant way, but in any case, I am writing it here for the future wanderer:

Let's say your filter name is "any"

User Space Plugin

You need headers that are not available outside the ebtables source. So, get the source code and go to the extensions folder. In the Makefile, add any to EXT_FUNC (these are the goals you need to create) and write the source ebt_any.c file as follows:

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

Note: if you have data coming from user space to kernel space, write something instead of struct whatever . I commented on this because I am not using anything.

Note. , even if your program does not require an option (for example, mine, which should have fit all), you need to specify the parameter anyway, because the way ebtables knows to use your filter.

Note: some of these functions seem unnecessary, but if you do not write them, you will get the error "BUG: bad merge".

Kernel space module

The kernel space module is simpler:

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

Note: if you use struct whatever in user space, you must use the same in kernel space.

Note: unlike a user-space plugin using ebtables headers / functions, the kernel module uses xtables instead instead !!

Compile the module (fairly standard) and install it for automatic loading. In addition, you can insmod and rmmod use the module yourself before adding / after removing ebtables rules.

How to make ebtables use your filter

Just add a rule containing --use-any some_value and you are kind. For instance:

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

Note: this --use-any is the option that was specified in ebt_u_match reg.extra_ops (which was defined in the _any_opts array) in the user space plugin.

+6
source

Source: https://habr.com/ru/post/1396857/


All Articles