博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
netfilter 结构整理
阅读量:7083 次
发布时间:2019-06-28

本文共 9647 字,大约阅读时间需要 32 分钟。

@(Linux network)

netfilter struct 整理

结构体关系图

阐述了结构体之间的关联

pic 1


xt_table

在net->netns_ipv4结构体中,包含了如下几个xt_table

  • iptable_filter
  • iptable_mangle
  • iptable_raw
  • arptable_filter
  • nat_filter
struct xt_table {    struct list_head list;//xt_table list    /* What hooks you will enter on */    // 此table中包含的chain,譬如nat table就不包含forward chain    // 在hook point,会去执行相应nf_hook[][] list上的hook_fn. 而不同的hook_fn会去查对应模块的table.    // 就是说, nat 注册的hook_fn 不会去在nat table中查找forward chain    unsigned int valid_hooks;    /* Man behind the curtain... */    // 具体存储table 内容    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 */    /* A unique name... */    // 表名    const char name[XT_TABLE_MAXNAMELEN];};

下面来看private指针指向的结构体,这个结构体中具体存储了xt_entry结构体,每个xt_entry对应一条规则。

struct xt_table_info {    /* Size per table */    // table 的大小    unsigned int size;    /* Number of entries: FIXME. --RR */    // 包含的entry个数    unsigned int number;    /* Initial number of entries. Needed for module usage count */    // table的起始entry offset    unsigned int initial_entries;    /* Entry points and underflows */    // hook_entry[] 存储了每个chain 对应的起始entry offset    // underflow[] 存储了每个chain 最后一个entry的offset    unsigned int hook_entry[NF_INET_NUMHOOKS];    unsigned int underflow[NF_INET_NUMHOOKS];    /*     * Number of user chains. Since tables cannot have loops, at most     * @stacksize jumps (number of user chains) can possibly be made.     */    // scott added:     // we can only jump form hook chains to user chains, PRE_ROUTING-> POST_ROUTING are not supported.    // so stacksize is the number of user chains and the max value of jump times.    // And also, jumpstack can only store child chain entry.    // 当chain之间发生jump的时候(A->B),只需要将A中当前的entry push进stack即可。所以jumpstack最大只需要存储user chains个数的entry.         // 如果B chain的某个entry target为XT_RETURN,则从stack中pop出A中的entry,并顺着A chain往下匹配.    unsigned int stacksize;    unsigned int __percpu *stackptr;    // 等同于 jumpstack[cpuid][entry*]    void ***jumpstack;        //保存的entries    unsigned char entries[0] __aligned(8);};

ipt_entry

ipt_entry具体的定义了每一条规则,例如

iptables -t nat -A PREROUTING -s 12.12.12.12 -ptcp --dport 808 -j DROP

/* 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 matchesstruct ipt_entry {    //存放了标准匹配    struct ipt_ip ip;    /* Mark with fields that we care about. */    unsigned int nfcache;    /* Size of ipt_entry + matches */    // 指定了target 元素的地址    // target_offset = elems + sizeof(xt_match) * numof(matchs)    __u16 target_offset;    /* Size of ipt_entry + matches + target */    // 下一个xt_entry的地址    __u16 next_offset;    /* Back pointer */    // 从哪个entry 过来的    unsigned int comefrom;    /* Packet and byte counters. */    // 计数 packet 和 byte?    struct xt_counters counters;    /* The matches (if any), then the target. */    // elems中保存了xt_match 和 xt_target.    // xt_match 和 xt_target 地址偏移在 target_offset指定    unsigned char elems[0];};

ipt_entry 看起来还是比较简单的,下面这张图解释的对ipt_entry比较清楚:

ipt_entry

注意ipt_ip结构中存放的是标准匹配,如 ip , netmask ,prototype,interface 等,扩展匹配等才存放在xt_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 */    //SYN, ACK, FIN, RST ...    __u8 flags;    /* Inverse flags */    __u8 invflags;};

xt_entry_match

xt_entry_match 中主要保存了拓展match,在iptables中用-m 表示,在下例中,使用拓展socket match:

iptables -t nat -A PREROUTING -m socket -j DIVERT

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];};

注意: 在/usr/include /下的头文件,提供的都是用户态编写程序的接口。只有真正kernel src中提供的include文件,才是编写内核代码时需要引入的头文件。

例如 xt_entry_match,在/usr/include/linux/netfilter/x_tables.h中和内核代码 /usr/src/kernels/3.10.0-514.el7.x86_64/include/linux/netfilter/都有定义,但是只有内核代码文件中才包含xt_match结构的定义。用户文件中是没有次结构定义的。

union struct

这块是用户和内核共同操作的一块地址。当我们通过iptables添加规则的时候,用户态也会创建xt_entry_match结构,并将user.name设置为match名称,内核拿到此结构后,通过name的值,找到匹配的xt_match结构,并使kernel.match指向它。也就是说,name的值会被覆盖,但是没有关系,因为存储在table chain中的时候,xt_entry_match不需要name,只需要xt_match即可。

这里我们需要关注的xt_match结构体,其具体指向了一个匹配

xt_match

xt_match是内核的匹配模块,需要先注册,才能使用。

xt_register_match(&pktsize_match);
也就是说,xt_match结构体是公用的,当创建多个xt_entry_match的时候,其指向的都是match list中的该match, 但是xt_entry_match是不同的。

struct xt_match {    //extend match list?    struct list_head list;        //match name    const char name[XT_EXTENSION_MAXNAMELEN];    u_int8_t revision;    /* Return true or false: return FALSE and set *hotdrop = 1 to           force immediate packet drop. */    /* Arguments changed since 2.6.9, as this must now handle       non-linear skb, using skb_header_pointer and       skb_ip_make_writable. */    //match 函数,判断sk_buff是否满足该match,入参为sk_buff报文 以及    //xt_action_param 用来match和target的参数    bool (*match)(const struct sk_buff *skb,              struct xt_action_param *);    /* Called when user tries to insert an entry of this type. */    // 新建match entry的时候check    int (*checkentry)(const struct xt_mtchk_param *);    /* Called when entry of this type deleted. */    // 删除该类型match 的时候调用    void (*destroy)(const struct xt_mtdtor_param *);#ifdef CONFIG_COMPAT    /* Called when userspace align differs from kernel space one */    void (*compat_from_user)(void *dst, const void *src);    int (*compat_to_user)(void __user *dst, const void *src);#endif    /* Set this to THIS_MODULE if you are a module, otherwise NULL */    struct module *me;    const char *table;    unsigned int matchsize;#ifdef CONFIG_COMPAT    unsigned int compatsize;#endif    unsigned int hooks;    unsigned short proto;    unsigned short family;};

注意: 这里重要的match指针函数,

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

skb 为需要处理的报文,xt_action_param则指向了匹配规则,网口信息等。这个后面还需要看这个参数是怎么构建以及传入的。

xt_action_param

mtach或者target操作的时候,传入的参数。这个结构体是被xt_match和xt_target公用的,因此很多参数采用union

// struct xt_action_param - parameters for matches/targets // // @match:    the match extension // @target:    the target extension // @matchinfo:    per-match data // @targetinfo:    per-target data // @in:        input netdevice // @out:    output netdevice // @fragoff:    packet is a fragment, this is the data offset // @thoff:    position of transport header relative to skb->data // @hook:    hook number given packet came from // @family:    Actual NFPROTO_* through which the function is invoked //        (helpful when match->family == NFPROTO_UNSPEC) // // Fields written to by extensions: // // @hotdrop:    drop packet if we had inspection problems // Network namespace obtainable using dev_net(in/out)struct xt_action_param {    union {        const struct xt_match *match;        const struct xt_target *target;    };    union {        //配置的match 匹配参数        const void *matchinfo, *targinfo;    };    const struct net_device *in, *out;    //分片报文的偏移量    int fragoff;    unsigned int thoff;    //packet从哪个hook点过来的    unsigned int hooknum;    u_int8_t family;    //hotdrop = 1立刻丢掉此packet    bool hotdrop;};

xt_entry_target

创建iptable 规则时指定的动作,xt_entry_target依赖xt_target,extend target 需要register到xt_af[pf].target list.

xt_entry_target , xt_target 和 xt_entry_match,xt_match的结构类似。

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];};
/* Registration hooks for targets. */struct xt_target {    struct list_head list;    const char name[XT_EXTENSION_MAXNAMELEN];    u_int8_t revision;    /* Returns verdict. Argument order changed since 2.6.9, as this       must now handle non-linear skbs, using skb_copy_bits and       skb_ip_make_writable. */    unsigned int (*target)(struct sk_buff *skb,                   const struct xt_action_param *);    /* Called when user tries to insert an entry of this type:           hook_mask is a bitmask of hooks from which it can be           called. */    /* Should return 0 on success or an error code otherwise (-Exxxx). */    int (*checkentry)(const struct xt_tgchk_param *);    /* Called when entry of this type deleted. */    void (*destroy)(const struct xt_tgdtor_param *);#ifdef CONFIG_COMPAT    /* Called when userspace align differs from kernel space one */    void (*compat_from_user)(void *dst, const void *src);    int (*compat_to_user)(void __user *dst, const void *src);#endif    /* Set this to THIS_MODULE if you are a module, otherwise NULL */    struct module *me;    const char *table;    unsigned int targetsize;#ifdef CONFIG_COMPAT    unsigned int compatsize;#endif    unsigned int hooks;    unsigned short proto;    unsigned short family;    RH_KABI_RESERVE(1)    RH_KABI_RESERVE(2)    RH_KABI_RESERVE(3)    RH_KABI_RESERVE(4)};

转载地址:http://ddmml.baihongyu.com/

你可能感兴趣的文章
Docker 学习资源整理
查看>>
maven实战
查看>>
HAproxy配置文件详解以及HAproxy的ACL详解
查看>>
Object-C NSData
查看>>
mysql升级
查看>>
我的友情链接
查看>>
安卓学习-Bitmaps与优化
查看>>
用JAVA和Websocket实现实时通讯
查看>>
如何/怎么激活win8/win8.1/windows8.1/
查看>>
windows做FTPserver的一种方法
查看>>
设计模式之迭代器模式
查看>>
MYSQL企业级应用(三)基本管理
查看>>
浅谈 JavaScript 模块化编程
查看>>
thinkphp 自动验证学习
查看>>
Java 面试题:类加载-main()-构造代码块-构造器的执行顺序和关系。
查看>>
for与while循环、break跳出循环、continue结束本次循环、exit退出脚本
查看>>
mysql主从复制与读写分离
查看>>
四周第一次(2月26
查看>>
Python模块
查看>>
Windows2012、windows2016配置多用户登录
查看>>