ebtables用のカスタムモジュールを作成する方法は?
質問
基本的に、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(®);
}
void cleanup_module(void)
{
xt_unregister_match(®);
}
モジュールを正常にロードしました。しかし、まるでそこにないかのようです。内部にログを入手していません match
と check
機能するので、ブリッジは明らかに私のフィルターを考慮していません。私は何が間違っているのですか?
最初にフィルターをロードし、最初にブリッジをセットアップするか、最初にeBtablesルールを設定することの多くの組み合わせを試しましたが、それらのどれも何も変更しませんでした。
PS橋自体が機能します。パッケージをドロップするためにポリシーを追加した場合、最終コンピューターでそれらを受け取らないため、eBtablesも有効であると確信しています。私が理解できないのは、私のフィルターも検討するようにeBtablesに伝える方法です。
解決
カーネルモジュールを使用するには、ユーザースペースプログラムに適したプラグインを記述する必要もあり、その後、それを呼び出すルールを挿入します。
オプションがない場合は、指定しないでください .matchsize
パラメーター struct xt_match
(指定0に等しい)。
他のヒント
私はこれを最もエレガントな方法ではなく機能させましたが、とにかく、私は将来の放浪者のためにここに書いています:
フィルター名が「任意」だとしましょう。
ユーザースペースプラグイン
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がフィルターを使用することを知っている方法だからです。
ノート: これらの機能の一部は不要に見えますが、それらを書かないと、「バグ:バッドマージ」エラーが表示されます。
カーネル空間モジュール
カーネル空間モジュールはよりシンプルです:
#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(®);
printk("Bridge initializing...done!\n");
return ret;
}
void cleanup_module(void)
{
printk("Bridge exiting...\n");
xt_unregister_match(®);
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
ノート: これ --use-any
それは option
それは与えられました ebt_u_match reg.extra_ops
(これは配列で定義されていました _any_opts
)ユーザースペースプラグイン。