linux netfilter rule match target 数据结构


对于netfilter 可以参考 https://netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-3.html

netfilter 框架中包含了:filter mat mangleraw security;

在net结构中的成员struct netns_xt xt,是用来存储所有table的,

netns_xt结构的成员如下,其中tables存储了多种协议对应的table链表,每种协议对应一个链表,多种table存储在自己所属协议的链表上;

struct netns_xt {
    struct list_head tables[NFPROTO_NUMPROTO];
    bool notrack_deprecated_warning;
    bool clusterip_deprecated_warning;
#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
};

每个具体类型的table如下:

/* Furniture shopping... */
struct xt_table {
    struct list_head list;
    /* What hooks you will enter on */
    unsigned int valid_hooks; /* 该表关注的钩子点 */
    /* Man behind the curtain... *//* 私有数据,真正的规则,指向xt_table_info */
    struct xt_table_info *private;
    /* Set this to THIS_MODULE if you are a module, otherwise NULL */
    struct module *me;
    u_int8_t af;        /* address/protocol family */ /* 协议族 */
    int priority;        /* hook order */ /* 优先级 */
    /* called when table is needed in the given netns */
    int (*table_init)(struct net *net);
    /* A unique name... */
    const char name[XT_TABLE_MAXNAMELEN];//表的名字
};

xt_table的private成员又指向了xt_table_info结构,存储真正的规则相关信息,包括入口和偏移

/* The table itself */
struct xt_table_info {
    /* Size per table */
    unsigned int size;  /* 表大小,占用的内存空间 */
    /* Number of entries: FIXME. --RR */
    unsigned int number;  /* 表中规则数量 */
    /* Initial number of entries. Needed for module usage count */
    unsigned int initial_entries;/* 初始的规则数量,用于模块计数 */

    /* Entry points and underflows 
*   hook_entries:记录所影响的HOOK的规则入口相对于下面的entries变量的偏移量
*   underflows:与hook_entry相对应的规则表上限偏移量
    */
    
    unsigned int hook_entry[NF_INET_NUMHOOKS];/* 钩子规则入口,相对于下面的entries偏移量 */
    unsigned int underflow[NF_INET_NUMHOOKS];  /* 与hook_entry相对应的规则表上限偏移量,当无规则录入时,hook_entry和underflow均为0 */
    /*
     * Number of user chains. Since tables cannot have loops, at most
     * @stacksize jumps (number of user chains) can possibly be made.
     */
    unsigned int stacksize;
    void ***jumpstack;
  /* 每个cpu的ipt_entry指针,指向ipt_entry的首地址 */
    unsigned char entries[0] __aligned(8);
};

xt_table_info结构的entries成员指向了匹配规则的入口,入口的每个数组包含了多个rule;

Netfilter 中规则是顺序存储的,一条rule规则主要包括三个部

  • ipt_entry:标准匹配结构,主要包含数据包的源、目的IP,出、入接口和掩码等;
  • ipt_entry_match:扩展匹配。一条rule规则可能有零个或多个ipt_entry_match结构;
  • ipt_entry_target:一条rule规则有且仅有一个target动作。就是当所有的标准匹配和扩展匹配都符合之后才来执行该target
      • /*ipt_entry中包含ipt_ip结构,用于标准match,匹配内容为源目的地址,入出口设备,协议等*/
        /* Yes, Virginia, you have to zero the padding. */
        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 */
            __u16 proto;/* 协议号 */
        
            /* Flags word */
            __u8 flags;
            /* Inverse flags */
            __u8 invflags; /* 是否是反转匹配 */
        };
        /* This structure defines each of the firewall rules.  Consists of 3
           parts which are 1) general IP header stuff 2) match specific
           stuff 3) the target to perform if the rule matches */
        struct ipt_entry {
            struct ipt_ip ip;
        
            /* Mark with fields that we care about. */
            unsigned int nfcache;
        
            /* Size of ipt_entry + matches */
            /* target区的偏移,通常target区位于match区之后,而match区则在ipt_entry的末尾;
        初始化为sizeof(struct ipt_entry),即假定没有match */
            __u16 target_offset;
            /* Size of ipt_entry + matches + target */
            /* 下一条规则相对于本规则的偏移,也即本规则所用空间的总和,
        初始化为sizeof(struct ipt_entry)+sizeof(struct ipt_target),即没有match */
        
            __u16 next_offset;
        
            /* Back pointer */
            unsigned int comefrom;
        
            /* Packet and byte counters. *//* 记录该规则处理过的报文数和报文总字节数 */
            struct xt_counters counters;
        
            /* The matches (if any), then the target. *//*target或者是match的起始位置 */
            unsigned char elems[0];
        };
        /*
        ipt_entry_match将内核态与用户态关联起来,按我的理解,内核和用户在注册和维护match时使用的是各自的match结构ipt_match和iptables_match,
        但在具体应用到某个规则时则需要统一成ipt_entry_match结构。
        前面说过,match区存储在ipt_entry的末尾,target在最后,结合ipt_entry_match的定义,可以知道一条具体的规则中存储的数据结构不是:
        ipt_entry + ipt_match1 + ipt_match2 + ipt_match3 + … + target
        而是:
        ipt_entry + ipt_entry_match1 + ipt_entry_match2 + ipt_entry_match3 + … + target
        */
        struct xt_entry_match {
            union {
                struct {
                    __u16 match_size;
                    /* Used by userspace */
                    char name[XT_EXTENSION_MAXNAMELEN];
                    __u8 revision;
                } user;
                struct {
                    __u16 match_size;
                    /* Used inside the kernel */
                    struct xt_match *match;
                } kernel;
                /* Total length */
                __u16 match_size;
            } u;
            unsigned char data[0];
        };
        /*

        在某条规则匹配之后,执行的动作;也分为标准target和扩展target;

        标准target:t->u.kernel.target->target为NULL,则为标准target,根据verdict返回值决定如何进行下一步处理;扩展target:t->u.kernel.target->target不为NULL,则为扩展target,这时候需要执行该target函数

        */
        struct xt_entry_target {
            union {
                struct {
                    __u16 target_size;
                    /* Used by userspace */
                    char name[XT_EXTENSION_MAXNAMELEN];
                    __u8 revision;
                } user;
                struct {
                    __u16 target_size;
                    /* Used inside the kernel */
                    struct xt_target *target;
                } kernel;
                /* Total length */
                __u16 target_size;
            } u;
            unsigned char data[0];
        xt_standard_target对xt_entry_target成员进行了封装,增加了verdict,该字段用于返回处理结果
        struct xt_standard_target {
            struct xt_entry_target target;
            int verdict;
        };
        
        };

        target主要用来处理:当某条规则中的所有match都被数据包匹配后该执行什么样的动作来处理这个报文,最后将处理后结果通过verdict值返回给Netfilter框架

优质内容筛选与推荐>>
1、android 用命令行打包生成 apk
2、swagger 注释方式编写接口文档
3、新版eclipse编写Android 时常常报的错误 -support-v7
4、阿里离线数据处理平台2013暑期学校
5、canvas背景透明


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn