Linux netfilter 学习笔记 之三 ip层netfilter的table、rule、match、target结构分析
来源:互联网 发布:淘宝电商卖家怎么做 编辑:程序博客网 时间:2024/05/21 13:57
分类: linux 网络 2014-06-22 14:35 3750人阅读 评论(1)收藏 举报
目录(?)[+]
- tablerulematchtarget等相关数据结构分析
- 1 xt_table
- 2 xt_table_info
- 3 ipt_entry
- 31 ipt_ip
- 4 ipt_entry_match
- 41 xt_match
- 5 ipt_standard_target
- 6 ipt_entry_target
- 61 xt_target
基于linux2.6.21
上一节分析了ip层hook回调函数的注册以及调用流程,本节我们就开始分析每一个模块的具体实现。 工欲善其事必先利其器,一个功能模块的代码实现与其数据结构的设计有很大的关系,所以我们本节主要是分析table、rule、match、target相关的数据结构,争取本节能把数据结构的定义以及数据结构之间的关系分析明了。
1. table、rule、match、target等相关数据结构分析
在分析table、rule、match、target之前,先把它们之间的联系图贴出来,看了这个图以后,我们基本上就知道xt_table里rule、match、target之间的关联了。
总体框架图
对于一个xt_table表,通过其private指针,指向了xt_table_info结构,而xt_table_info中的entries指针数组的每一个指针成员指向xt_table表在相应cpu中的rule的首地址。
一个表中的所有rule在一个连续的内存块中,让所有rule在一个连续的内存块中,使对rule规则的遍历寻址成为了可能,因为一个规则相对于下一个规则并没有使用链表的形式连接在一起。
而一个完整的rule规则,包括了ipt_entry、ipt_entry_match、ipt_standard_target组成(其实ipt_entry就代表了一个规则,通过ipt_entry->elems即可找到该规则对应的match)。
下面我们一一分析上图提到的数据结构。
1.1 xt_table
该结构体对应于iptables中的表,目前内核注册的table有filter、mangle、nat、raw表,而这些table根据pf值添加到xt_af[pf].tables链表中。而一个xt_table中包含了该表所支持的hook点与该表里已添加的所有rule规则。
- struct xt_table
- {
- /*用于将xt_table连接在一起的链表成员*/
- struct list_head list;
- /*表名*/
- char name[XT_TABLE_MAXNAMELEN];
- /*该表所感兴趣的hook点*/
- unsigned int valid_hooks;
- /*读写锁*/
- rwlock_t lock;
- /*指针,指向xt_table_info,这个指针指向的xt_table_info才是表的重要成员
- 用于存放规则链*/
- void *private;
- /* 判断该表是否属于一个模块 */
- struct module *me;
- /*协议号*/
- int af;
- };
1.2 xt_table_info
上面分析xt_table时,我们只xt_table通过private指针指向了xt_table_info,xt_table_info里面包括了表中含有的规则,是表比较重要的结构体。
- struct xt_table_info
- {
- /*在一个cpu内,该xt_table所包含的所有规则的内存总数(以字节为单位)*/
- unsigned int size;/*规则的个数*/
- unsigned int number;/*初始化时的规则格式*/
- unsigned int initial_entries;
- /*每条规则链相对于第一条规则链的偏移量*/
- unsigned int hook_entry[NF_IP_NUMHOOKS];/*这个具体用在什么地方我还没有搞懂,看别人的解释为每一条规则链范围的最大
- 上限,不过我看初始化时,其与hook_entry在对应规则链上的值是相等的,目前我在代码里发现对underflow的调用,基本上都是将其与hook_entry在对应规则链上的值设置为
- 相同的,还需要深入分析后确认*/
- unsigned int underflow[NF_IP_NUMHOOKS];
- /* ipt_entry tables: one per CPU */
- /*每一个cpu里,ipt_entry指针,指向ipt_entry规则的首地址*/
- char *entries[NR_CPUS];
- };
关于ipt_tale_info与ipt_table、ipt_entry的关系见上面的总体架构图。
1.3 ipt_entry
下面我们分析下ipt_entry
- struct ipt_entry
- {
- struct ipt_ip ip;
- /* Mark with fields that we care about. */
- unsigned int nfcache;
- /* Size of ipt_entry + matches */
- /*该规则中target结构相对于该ipt_entry首地址的偏移量*/
- u_int16_t target_offset;
- /* Size of ipt_entry + matches + target */
- /* 下一个规则相对于该ipt_entry首地址的偏移量*/
- u_int16_t next_offset;
- /* 这个变量的用途有两个:
- 1.判断table表中的规则链是否存在环路
- 2.遍历规则链链时,用于用户自定义链的规则执行完时返回到主链时使用*/
- unsigned int comefrom;
- /* Packet and byte counters. */
- struct xt_counters counters;
- /*由于在设计时需要match结构与ipt_entry的内存是连续的,但是一个ipt_entry包含的match个数又是可变的,所以定义了一个可变长度数组elems,主要是为了实现动态的申请match内存空间*/
- unsigned char elems[0];
- };
1.3.1 ipt_ip
对应的ipt_ip定义如下,其主要用于标准匹配
/*
标准匹配时的匹配条件
*/
- struct ipt_ip {
- /* 源、目的ip地址 */
- struct in_addr src, dst;
- /* 源、目的ip地址的掩码*/
- 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*/
- u_int8_t flags;
- /*是否是反转匹配*/
- /* Inverse flags */
- u_int8_t invflags;
- };
一个ipt_entry的整体结构如上图。
1.4 ipt_entry_match
我们使用到ipt_entry_match时,就说明这是一个扩展match,对于一个标准match是通过调用函数ip_packet_match,对ipt_entry->ip进行判断来实现的,只有扩展match才会使用该结构体在ipt_entry中添加一个ipt_entry_match变量。
match结构体,包括用户态与内核态联合体,通过这个联合体我们发现
只有match_size是共用的。当用户态需要添加新的规则时,对于新规则的
match,用户态只在ipt_entry_match.u.user.name中设置match的名称,而内核在添加规则时
就会根据ipt_entry_match.u.user.name在链表xt[af].match中查找符合要求的ipt_entry_match,当查找
到时就会对ipt_entry_match.u.kernel.match 进行赋值
- struct ipt_entry_match
- {
- union {
- struct {
- /*该match所占用的内存大小(以字节为单位)*/
- u_int16_t match_size;
- /*该match的名称*/
- char name[IPT_FUNCTION_MAXNAMELEN-1];
- /*该match的版本,
- 通过match的名称与版本信息可以唯一确定一个match。
- */
- u_int8_t revision;
- } user;
- struct {
- /*该match所占用的内存大小(以字节为单位)*/
- u_int16_t match_size;
- /*指向ipt_match结构,对于*/
- struct ipt_match *match;
- } kernel;
- /* Total length */
- u_int16_t match_size;
- } u;
- /*可变长度数组,与下一个match或者target关联*/
- unsigned char data[0];
- };
ipt_entry_match相关的结构体图如下:
上图是一个ipt_entry_match与ipt_match以及一个ipt_match与xt_af[2].match之间的关联,当我们定义了一个xt_match(xt_match与ipt_match是同一个结构)时,需要将其插入到相应的xt_af[pf].match链表中。而当我们为一个rule规则添加一个扩展match时,根据ipt_entry_match.u.user.name查找xt_af[pf].match链表,当查找到相应的xt_match时,就将其地址赋值给ipt_entry_match.u.kernel.match(将该图与总体框架图搭配使用,就基本明了ipt_table、ipt_table_info、ipt_entry、ipt_entry_match、xt_match、xt_af[pf].match这几个数据结构之间的关系)。
1.4.1 xt_match
而xt_match的定义如下:
- struct xt_match
- {
- struct list_head list; //链表,使该match添加到match链表中
- const char name[XT_FUNCTION_MAXNAMELEN-1];//match名称
- 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处理函数
- */
- int (*match)(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop);
- /* Called when user tries to insert an entry of this type. */
- /* Should return true or false. */
- /*合法性检查函数,在创建一个ipt_entry时,在为其match指针赋值后,即会调用该函数
- 进行合法性检查,当检查失败后,即会返回失败,且说明ipt_table创建失败*/
- int (*checkentry)(const char *tablename,
- const void *ip,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask);
- /* Called when entry of this type deleted. */
- /*销毁函数*/
- void (*destroy)(void *matchinfo, unsigned int matchinfosize);
- /* Set this to THIS_MODULE if you are a module, otherwise NULL */
- struct module *me;
- };
如果我们想要添加一个扩展match,就要初始化一个xt_match结构,并且将插入到xt_af[pf].match链表
1.5 ipt_standard_target
该结构体主要是对ipt_entry_target的封装,且增加了变量verdict。
这个verdict起到了很大的作用。
对于target,我们需要知道target有两大类,标准target与扩展target
a)对于标准target,其ipt_entry_target.u.kernel.target为NULL,其只需返回NF_ACCEPT/NF_DROP等操作。
b)对于扩展target,需要调用ipt_entry_target.u.kernel.target,执行扩展target操作,并根据返回值决定是否允许数据通行。
即扩展匹配是根据ipt_entry_target.u.kernel.target决定数据包下一步的执行操作,那标准匹配是根据什么决定数据包下一步的操作的呢?
答案就是verdict,当verdict为小于0时,则-verdict则为数据包下一步的执行操作;当verdict大于0时,则说明该target需要跳转到一个用户自定义链的链首地址,其值为用户自定义链相对于表的第一条链规则的偏移量。
基于以上,我们知道verdict的存在即指明了标准target的动作,又为用户链的存在并生效提供了可能。
- struct ipt_standard_target
- {
- struct ipt_entry_target target;
- int verdict;
- };
1.6 ipt_entry_target
虽然与ipt_entry_match定义相同,但是ipt_entry_target既可以表示一个标准target,也可以表示一个扩展target。当是一个标准的target时,其ipt_entry_target.u.kernel.target为NULL。
下面我们分析一下这个结构体:
/*
target结构体,包括用户态与内核态联合体,通过这个联合体我们发现
只有target_size是共用的。当用户态需要添加新的规则时,对于新规则的
target,用户态只在ipt_entry_target.u.user.name中设置target的名称,而内核在添加规则时
就会根据ipt_entry_target.u.user.name在链表xt[af].target中查找符合要求的ipt_standard_target,当查找
到时就会对ipt_entry_target.u.kernel.target 进行赋值
*/
- struct ipt_entry_target
- {
- union {
- struct {
- u_int16_t target_size; //target 所占用的内存大小
- /* Used by userspace */
- char name[IPT_FUNCTION_MAXNAMELEN-1];//target 的名字
- /*target的版本号,这个值也有很大的作用,这个值让target的向 上兼容成为了可能。
- 存在以下情况:
- 对于target名称为"ABC ",revision为0的target,我们想对这个 target的扩展target函数做新的架构修改,但是又不想改target的 名称,也不想直接改原target的扩展target函数,这时我们可以重 新添加一个target名称为"ABC",revision为1,且扩展target函数
- 为我们新编写的target。这样既保证了针对原来target "ABC"的 iptables规则能正确执行,又能满足我们新的需求。
- 通过name与revision可以唯一确定一个target
- */
- u_int8_t revision;
- } user;
- struct {
- /*target 所占用的内存大小*/
- u_int16_t target_size;
- /* 扩展target使用,用于指向xt_target */
- struct ipt_target *target;
- } kernel;
- /*target 所占用的内存大小*/
- u_int16_t target_size;
- } u;
- /*可变长数组,与下一个ipt_entry关联*/
- unsigned char data[0];
- };
ipt_entry_target相关的结构体图如下:
上图是一个ipt_entry_target与ipt_target以及一个ipt_target与xt_af[2].target之间的关联,当我们定义了一个xt_target(xt_target与ipt_target是同一个结构)时,需要将其插入到相应的xt_af[pf].target链表中。而当我们为一个rule规则添加一个扩展target时,根据ipt_entry_target.u.user.name查找xt_af[pf].target链表,当查找到相应的xt_target时,就将其地址赋值给ipt_entry_target.u.kernel.tagret(将该图与总体框架图搭配使用,就基本明了ipt_table、ipt_table_info、ipt_entry、ipt_entry_target、xt_target、xt_af[pf].target这几个数据结构之间的关系)。
1.6.1 xt_target
xt_target的定义如下:
- struct xt_target
- {
- struct list_head list;//链表,使该match添加到target链表中
- const char name[XT_FUNCTION_MAXNAMELEN-1];//target 名称
- u_int8_t revision;
- /*
- target处理函数,对于SNAT、DNAT即在其target函数里,更新request或者reply方向 ip_conntrack_tuple值
- */
- unsigned int (*target)(struct sk_buff **pskb,
- const struct net_device *in,
- const struct net_device *out,
- unsigned int hooknum,
- const void *targinfo,
- void *userdata);
- /*合法性检查函数,在创建一个ipt_entry时,在为其target指针赋值后,即会调用该函数
- 进行合法性检查,当检查失败后,即会返回失败,且说明ipt_table创建失败*/
- int (*checkentry)(const char *tablename,
- const void *entry,
- void *targinfo,
- unsigned int targinfosize,
- unsigned int hook_mask);
- /*销毁函数,当删除一个规则时调用*/
- void (*destroy)(void *targinfo, unsigned int targinfosize);
- /* 该target是否属于一个模块 */
- struct module *me;
- };
当我们想要添加一个扩展target,就要初始化一个xt_target结构,并且将插入到xt_af[pf].target链表
至此,基本上就把三层netfilter相关的数据结构一一介绍完了,综合以上分析,结合上面的结构关联图,就把结构体ipt_table、ipt_table_info、ipt_entry、ipt_entry_target、xt_target、xt_af[pf].target、xt_af[pf].match、xt_af[pf].tables、xt_match、ipt_ip之间的关联也介绍清楚了。至此,万事俱备,就差分析表的创建、初始化、添加规则、删除规则、遍历表规则、添加match、添加target等具体实现了。只要对数据结构之间的关系清楚了,分析这些功能的实现就顺理成章了。
- Linux netfilter 学习笔记 之三 ip层netfilter的table、rule、match、target结构分析
- Linux netfilter 学习笔记 之三 ip层netfilter的table、rule、match、target结构分析
- Linux netfilter 学习笔记 之四 ip层netfilter的table注册及规则的添加
- Linux netfilter 学习笔记 之五 ip层netfilter的table中规则的匹配检查
- Linux netfilter 学习笔记 之五 ip层netfilter的table中规则的匹配检查
- Linux netfilter 学习笔记 之四 ip层netfilter的table注册及规则的添加
- Linux netfilter 学习笔记 之五 ip层netfilter的table中规则的匹配检查
- Linux netfilter 学习笔记 之九 ip层netfilter的连接跟踪模块代码分析
- Linux netfilter 学习笔记 之十二 ip层netfilter的NAT模块代码分析
- Linux netfilter 学习笔记 之十二 ip层netfilter的NAT模块代码分析
- Linux netfilter 学习笔记 之九 ip层netfilter的连接跟踪模块代码分析
- Linux netfilter 学习笔记 之七 ip层netfilter的连接跟踪模块的概念及相关的数据结构分析
- Linux netfilter 学习笔记 之七 ip层netfilter的连接跟踪模块的概念及相关的数据结构分析
- Linux netfilter 学习笔记 之二 ip 层netfilter的hook 注册以及执行hook函数的概要分析
- Linux netfilter 学习笔记 之六 ip层netfilter的filter表的创建及其hook函数分析
- Linux netfilter 学习笔记 之六 ip层netfilter的filter表的创建及其hook函数分析
- Linux netfilter 学习笔记 之二 ip 层netfilter的hook 注册以及执行hook函数的概要分析
- (三)洞悉linux下的Netfilter&iptables:内核中的rule,match和target
- 嵌入式的根文件系统
- SQL不同数据库下的查询前n条记录
- 洋洋洒洒c作业
- [leetcode] Binary Tree Right Side View
- LXT6架构-嵌入式Web服务器Nginx交叉编译与配置使用(ARMv7)
- Linux netfilter 学习笔记 之三 ip层netfilter的table、rule、match、target结构分析
- Genymotion模拟器不能上网的解决办法
- 【LeetCode】Valid Parentheses
- cf 7a Kalevitch and Chess
- Mac系统显示和隐藏文件夹
- Positional parameter does not exist: 1 in query: from Books where isbn=?
- 使用Python工具抓取网页
- HDU1045
- KMP字符串模式匹配详解