Netfilter中规则(rule)的组织框架

来源:互联网 发布:海淀区单片机竞赛成绩 编辑:程序博客网 时间:2024/06/06 02:16
1、大蓝图

table->chain->rule(match:target)

从上图所示,在内核空间,每个CPU上维护了一份rule的拷贝。这样做是为了减少锁的使用及增加硬件L1 cache的命中次数,以空间换时间

2table(表)

include/linux/netfilter/x_table.h

struct xt_table

{

    struct list_head list;

    unsigned int valid_hooks; /*该表中有效的hook点位图*/

    struct xt_table_info *private; //指向真正存储rule的结构体

    struct module *me;

    u_int8_t af; /* address/protocol family */

    const char name[XT_TABLE_MAXNAMELEN];//表名字

};

 

struct xt_table_info

{

    unsigned int size; //表的大小

    unsigned int number; //表中存的rule个数

    unsigned int initial_entries;//初始化表时创建的默认rule个数
  
//各个hook(chain)在表中的偏移量

    unsigned int hook_entry[NF_INET_NUMHOOKS]; 
    //各个hook(chain)中默认规则在表中的偏移量

    unsigned int underflow[NF_INET_NUMHOOKS];
    //数组,存储各个cpu上自己rule拷贝的内存首地址

    void *entries[1]; 

};

 

表的注册:

每个网络命名空间管理自己Netfilter中创建的table。并把这些表链接到相应的协议族链表里。

这样就可以通过用户空间传下来的表名查找到相应的表了。

struct net

{

struct netns_xt xt;

}

 

struct netns_xt 

{

    struct list_head tables[NFPROTO_NUMPROTO];

    #if defined(CONFIG_BRIDGE_NF_EBTABLES) || \

    defined(CONFIG_BRIDGE_NF_EBTABLES_MODULE)

    struct ebt_table *broute_table;

    struct ebt_table *frame_filter;

    struct ebt_table *frame_nat;

    #endif

};

struct xt_table *xt_register_table(struct net *net,

   const struct xt_table *input_table,

   struct xt_table_info *bootstrap,

   struct xt_table_info *newinfo)

{

    int ret;

    struct xt_table_info *private;

    struct xt_table *t, *table;

 

    /*申请x_table内存*/

    table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL);

    if (!table) {

        ret = -ENOMEM;

        goto out;

    }

 

    ret = mutex_lock_interruptible(&xt[table->af].mutex);

    if (ret != 0)

        goto out_free;

 

    /* 在命名空间里查找是否有相同名字的表 */

    list_for_each_entry(t, &net->xt.tables[table->af], list) {

        if (strcmp(t->name, table->name) == 0) {

            ret = -EEXIST;

            goto unlock;

        }

    }

 

    /* 初始化table_private*/

    table->private = bootstrap;

    if (!xt_replace_table(table, 0, newinfo, &ret))

        goto unlock;

    private = table->private;

    /* save number of initial entries */

    private->initial_entries = private->number;

     //把表挂到对应网络命名空间管理的链表上

    list_add(&table->list, &net->xt.tables[table->af]);

    mutex_unlock(&xt[table->af].mutex);

    return table;

 
unlock:

    mutex_unlock(&xt[table->af].mutex);

    out_free:

    kfree(table);

out:

    return ERR_PTR(ret);

}


3rule在内核中的定义和存储

不同的协议族定义的rule不同。为了通用,netfilter把各个协议族的一些共性的数据结构提取出来单独定义,各个协议族再自己定义自己独有的数据结构,并包含netfilter提供的通用数据结构。

 

我们以IPv4为例来看一下,通过用户空间的iptables所配置到内核中的每条rule是怎么存储的。

如图,ip_entry 是标准的匹配规则,ipt_entry_match是扩展的匹配规则,是可选项。每个rule最后带一个targetTraget有系统自带的,也有扩展的。

 

1、标准的匹配规则

struct ipt_entry

{

    struct ipt_ip ip; //五元组,ipv4报文通用的匹配元素

    /* Mark with fields that we care about. */

    unsigned int nfcache;

/*详见上图,rule首地址到target的偏移量*/

    /* Size of ipt_entry + matches */

    u_int16_t target_offset; 

    /* Size of ipt_entry + matches + target */
    /*下一条rule的偏移量*/

    u_int16_t next_offset;

 

    /* Back pointer */

    unsigned int comefrom;
    /*命中报文的统计计数*/

    /* Packet and byte counters. */

    struct xt_counters counters;

 

    /* The matches (if any), then the target. */

    unsigned char elems[0];

};

 

ipv4报文通用的匹配元素,源/目的ip地址/掩码,源/目的接口名/接口名掩码,传输层协议类型

struct ipt_ip 

{

    /* Source and destination IP addr */

    struct in_addr src, dst;

    /* Mask for src and dest IP addr */

    struct in_addr smsk, dmsk;

    char iniface[IFNAMSIZ], outiface[IFNAMSIZ];

    unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];

    /* Protocol, 0 = ANY */

    u_int16_t proto;

 

    /* Flags word */

    u_int8_t flags;

    /* Inverse flags */
    //位图,每一位代表以上匹配元素配置时是否是带!符号(取反)

    u_int8_t invflags;

};

4. 扩展的Macth

#define ipt_entry_match xt_entry_match

netfilter定义了一个通用的match数据结构struct xt_match

struct xt_match

{

    struct list_head list;
    //match名字,和iptables配置的-m参数相同

    const char name[XT_FUNCTION_MAXNAMELEN-1];

    u_int8_t revision;

    //规则匹配函数

    bool (*match)(const struct sk_buff *skb,

              const struct xt_match_param *);

 

    /* 匹配函数入参检查函数 */

    bool (*checkentry)(const struct xt_mtchk_param *);

 

    /* Called when entry of this type deleted. */

    void (*destroy)(const struct xt_mtdtor_param *);
    。。。。。。

    const char *table;
    //match的自定义数据长度

    unsigned int matchsize;

    unsigned int compatsize;

    unsigned int hooks;

    unsigned short proto;

    unsigned short family;

};

 

每个struct xt_match代表一个扩展matchnetfilter中各个扩展match自己定义自己的匹配参数数据结构,自己实现匹配函数。

 

netfilter中,每个扩展match 被注册到全局变量xt管理的match链表上,可根据match的名字来找到相应的struct xt_match

 

用户使用-m 来配置的扩展match下发给内核,在内核中以struct xt_entry_match数据结构来存储,该结构后紧跟着存储着扩展match自定义的匹配参数数据。

 

Match的基本处理流程

1、取到rule中存储的xt_entry_match,这里记录着iptables下发给内核的值,同时找到内核中注册的xt_match,从xt_match里找到相应的match函数.

2、根据xt_entry_match中记录的配置值初始化xt_match_param,

3、把报文和xt_match_param传给match函数进行匹配处理。

 

 

注册match

Int xt_register_match(struct xt_match *match)

{

    u_int8_t af = match->family;

    int ret;

    ret = mutex_lock_interruptible(&xt[af].mutex);

    if (ret != 0)

    return ret;

    list_add(&match->list, &xt[af].match);//加入Netfilter管理的全局Match链表上

    mutex_unlock(&xt[af].mutex);

 

    return ret;

}


5. Target

Netfilter中对扩展target 和扩展match的管理非常相似


target分扩展target和标准target

#define ipt_entry_target xt_entry_target

 

标准target

#define ipt_standard_target  xt_standard_target

struct xt_standard_target

{

    struct xt_entry_target target;

//verdict 可以是指定返回值,也可以是goto到下一个rule的偏移量,

也可以是queue的队列号。

    int verdict;

};

 

如果struct xt_entry->target 值为空,表示是标准target,根据verdict值来处理报文。

 

如果struct xt_entry->target不为空,表示不是标准target,就使用targettarget函数返回值来处理报文。

 

调用函数xt_register_target()来注册扩展target
0 0
原创粉丝点击