Netfilter源代码分析详解

上传人:m**** 文档编号:155307168 上传时间:2022-09-23 格式:DOCX 页数:38 大小:74.96KB
收藏 版权申诉 举报 下载
Netfilter源代码分析详解_第1页
第1页 / 共38页
Netfilter源代码分析详解_第2页
第2页 / 共38页
Netfilter源代码分析详解_第3页
第3页 / 共38页
资源描述:

《Netfilter源代码分析详解》由会员分享,可在线阅读,更多相关《Netfilter源代码分析详解(38页珍藏版)》请在装配图网上搜索。

1、一、概述1. Netfilter/IPTables 框架简介Netfilter/IPTables 是继 2.0.x 的 IPfwadm、2.2.x 的 IPchains 之后,新一代 的 Linux 防火墙机制。 Netfilter 采用模块化设计,具有良好的可扩充性。其重要 工具模块 IPTables 连接到 Netfilter 的架构中,并允许使用者对数据报进行过滤、 地址转换、处理等操作。Netfilter 提供了一个框架,将对网络代码的直接干涉降到最低,并允许用 规定的接口将其他包处理代码以模块的形式添加到内核中,具有极强的灵活性。2. 主要源代码文件 Linux 内核版本: 2.4.

2、21 Netfilter 主文件: net/core/netfilter.cNetfilter 主头文件:include/linux/netfilter.h IPv4 相关:c 文件: net/ipv4/netfilter/*.c头文件: include/linux/netfilter_ipv4.hinclude/linux/netfilter_ipv4/*.h IPv4 协议栈主体的部分 c 文件,特别是与数据报传送过程有关的部分:ip_input.c,ip_forward.c,ip_output.c,ip_fragment.c 等二、Netfilter/IPTablesIPv4 总体架构N

3、etfilter主要通过表、链实现规则,可以这么说,Netfilter是表的容器,表是链的容器,链是规则的容器,最终形成对数据报处理规则的实现。详细地说, Netfilter/IPTables 的体系结构可以分为三个大部分:1. Netfilter 的 HOOK 机制Netfilter 的通用框架不依赖于具体的协议,而是为每种网络协议定义一套 HOOK 函数。这些 HOOK 函数在数据报经过协议栈的几个关键点时被调用,在 这几个点中,协议栈将数据报及 HOOK 函数标号作为参数,传递给 Netfilter 框 架。对于它在网络堆栈中增加的这些HOOK,内核的任何模块可以对每种协议 的一个或多个

4、 HOOK 进行注册,实现挂接。这样当某个数据报被传递给 Netfilter 框架时,内核能检测到是否有任何模块对该协议和 HOOK 函数进行了注册。若 注册了,则调用该模块的注册时使用的回调函数,这样这些模块就有机会检查、 修改、丢弃该数据报及指示 Netfilter 将该数据报传入用户空间的队列。这样, HOOK 提供了一种方便的机制:在数据报通过 Linux 内核的不同 位置上截获和操作处理数据报。2. IPTables 基础模块IPTables 基础模块实现了三个表来筛选各种数据报,具体地讲, Linux2.4 内核提供的这三种数据报的处理功能是相互间独立的模块,都基于 Netfilt

5、er 的 HOOK函数和各种表、链实现。这三个表包括:filter表,nat表以及mangle表。3. 具体功能模块1.1. 数据报过滤模块2. 连接跟踪模块(Conntrack)3. 网络地址转换模块(NAT)4. 数据报修改模块( mangle)5. 其它高级功能模块于是,Netfilter/IPTables总体架构如图 所示三、HOOK的实现1. Netfilter-IPv4 中的 HOOKNetfilter 模块需要使用 HOOK 来启用函数的动态钩接,它在 IPv4 中定义了 五个 HOOK (位于文件 include/linux/netfilter_ipv4.h. Line 39)

6、,分别对应 0-4 的 hooknum简单地说,数据报经过各个 HOOK 的流程如下:数据报从进入系统,进行 IP 校验以后,首先经过第一个 HOOK 函数 NF_IP_PRE_ROUTING 进行处理;然后就进入路由代码,其决定该数据报是需 要转发还是发给本机的;若该数据报是发被本机的,则该数据经过 HOOK 函数 NF_IP_LOCAL_IN 处理以后然后传递给上层协议;若该数据报应该被转发则它 被 NF_IP_FORWARD 处理;经过转发的数据报经过最后一个 HOOK 函数 NF_IP_POST_ROUTING 处理以后,再传输到网络上。本地产生的数据经过 HOOK 函数 NF_IP_

7、LOCAL_OUT 处理后,进行路由选择处理,然后经过 NF_IP_POST_ROUTING 处理后发送出去。总之,这五个 HOOK 所组成的 Netfilter-IPv4 数据报筛选体系如图 (注:下面所 说Netfilter/IPTables均基于IPv4,不再赘述)详细地说,各个 HOOK 及其在 IP 数据报传递中的具体位置如图 NF_IP_PRE_ROUTING (0)数据报在进入路由代码被处理之前,数据报在IP数据报接收函数ip_rcv() (位于net/ipv4/ip_input.c,Line379)的最后,也就是在传入的数据报被处理之 前经过这个HOOK。在ip_rcv()中挂

8、接这个HOOK之前,进行的是一些与类型、 长度、版本有关的检查。经过这个HOOK处理之后,数据报进入ip_rcv_finish()(位于 net/ipv4/ip_input.c,Line306),进行查路由表的工作,并判断该数据报是发给本 地机器还是进行转发。在这个 HOOK 上主要是对数据报作报头检测处理,以捕获异常情况。涉及功能(优先级顺序):Conntrack(-200)、mangle(-150)、DNAT(-IOO) NF_IP_LOCAL_IN (1)目的地为本地主机的数据报在 IP 数据报本地投递函数 ip_local_deliver() (位于 net/ipv4/ip_input

9、.c,Line290)的最后经过这个 HOOK。经过这个HOOK处理之后,数据报进入ip_local_deliver_finish()(位于 net/ipv4/ip_input.c, Line219)这样,IPTables模块就可以利用这个HOOK对应的INPUT规则链表来 对数据报进行规则匹配的筛选了。防火墙一般建立在这个 HOOK 上。涉及功能:mangle(-150)、filter(O)、SNAT(IOO)、Conntrack(INT_MAX-l) NF_IP_FORWARD (2)目的地非本地主机的数据报,包括被 NAT 修改过地址的数据报,都要在 IP 数据报转发函数 ip_forw

10、ard()(位于 net/ipv4/ip_forward.c, Line73 )的最后经 过这个 HOOK。经过这个HOOK处理之后,数据报进入ip_forward_finish()(位于 net/ipv4/ip_forward.c, Line44)另外,在 net/ipv4/ipmr.c 中的 ipmr_queue_xmit()函数(Line1119)最后也 会经过这个HOOK(ipmr为多播相关,估计是在需要通过路由转发多播数据 时的处理)这样, IPTables 模块就可以利用这个 HOOK 对应的 FORWARD 规则链 表来对数据报进行规则匹配的筛选了。涉及功能: mangle(-1

11、50)、 filter(0) NF_IP_LOCAL_OUT (3)本地主机发出的数据报在 IP 数据报构建/发送函数 ip_queue_xmit() 位于 net/ipv4/ip_output.c, Line339)、以及 ip_build_and_send_pkt()(位于 net/ipv4/ip_output.c, Line122)的最后经过这个HOOK。(在数据报处理中,前 者最为常用,后者用于那些不传输有效数据的 SYN/ACK 包)经过这个HOOK处理后,数据报进入ip_queue_xmit2()(位于 net/ipv4/ip_output.c, Line281)另外,在 ip_b

12、uild_xmit_slow()(位于 net/ipv4/ip_output.c,Line429 )和 ip_build_xmit()(位于 net/ipv4/ip_output.c,Line638)中用于进行错误检测;在 igmp_send_report()(位于 net/ipv4/igmp.c, Line195)的最后也经过了这个 HOOK, 进行多播时相关的处理。这样, IPTables 模块就可以利用这个 HOOK 对应的 OUTPUT 规则链表 来对数据报进行规则匹配的筛选了。涉及功能: Conntrack(-200)、 mangle(-150)、 DNAT(-100)、 filte

13、r(0) NF_IP_POST_ROUTING (4)所有数据报,包括源地址为本地主机和非本地主机的,在通过网络设备 离开本地主机之前,在IP数据报发送函数ip_finish_output()(位于 net/ipv4/ip_output.c, Linel84)的最后经过这个 HOOK。经过这个HOOK处理后,数据报进入ip_finish_output2()(位于 net/ipv4/ip_output.c, Line160)另外,在函数 ip_mc_output()(位于 net/ipv4/ip_output.c, Line195)中在克隆新的网络缓存skb时,也经过了这个HOOK 进行处理。涉

14、及功能:mangle(-150)、SNAT(100)、Conntrack(INT_MAX)其中,入口为 net_rx_action()(位于 net/core/dev.c,Line1602),作用是 将数据报一个个地从 CPU 的输入队列中拿出,然后传递给协议处理例程。出口为 dev_queue_xmit()(位于 net/core/dev.c,Line1035),这个函数被 高层协议的实例使用,以数据结构 struct sk_buff *skb 的形式在网络设备上发送 数据报。2. HOOK 的调用HOOK 的调用是通过宏 NF_HOOK 实现的,其定义位于 include/linux/Ne

15、tfilter.h, Line122:#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) / (list_empty(&nf_hooks(pf)(hook) /(okfn)(skb) /: nf_hook_slow(pf), (hook), (skb), (indev), (outdev), (okfn)这里先调用 list_empty 函数检查 HOOK 点存储数组 nf_hooks 是否为空, 为空则表示没有 HOOK 注册,则直接调用 okfn 继续处理。如果不为空,则转入 nf_hook_slow()函数。nf_hook_slow()

16、函数(位于 net/core/netfilter.c,Line449)的工作主要是读 nf_hook数组遍历所有的nf_hook_ops结构,并调用nf_hookfn()处理各个数据报。即 HOOK 的调用过程如图 所示下面说明一下 NF_HOOK 的各个参数:pf:协议族标识,相关的有效协议族列表位于include/linux/socket.h,Line 178。对于IPv4,应该使用协议族PF_INET; hook : HOOK 标识,即前面所说 5 个 HOOK 对应的 hooknum ; skb:是含有需要被处理包的sk_buuff数据结构的指针。sk_buff是Linux 网络缓存,

17、指那些 linux 内核处理 IP 分组报文的缓存,即套接字缓冲区。网卡收到IP分组报文后,将它们放入sk_buff,然后再传送给网络堆栈,网络堆 栈几乎一直要用到sk_buff。其定义在include/linux/skbuff.h, Line 129,下面列出 我认为对分析有意义的部分成员:o struct sock *sk;:指向创建分组报文的socket;o struct timeval stamp;:分组报文到达系统的时间;o下面是二个union,存放的是各层中各种协议的报文头指针:h对应传输层的报头nh对应网络层的报头 mac对应MAC层的报头o unsigned int len;:

18、套接字缓存所代表的报文长度,即从unsigned char *data; 的位置算起的当前有效报文长度。o unsigned char pkt_type,:表示报文的类型,具体类型定义在 include/linux/if_packet.h, Line24:#define PACKET_HOST 0 / 发送到本机的报文#define PACKET_BROADCAST 1 / 广播报文#define PACKET_MULTICAST 2 / 多播报文#define PACKET_OTHERHOST 3 / 表示目的地非本机但被本机 接收的报文#define PACKET_OUTGOING 4 /

19、 离开本机的报文/* These ones are invisible by user level */#define PACKET_LOOPBACK 5 / 本机发给自己的报文#define PACKET_FASTROUTE 6 / 快速路由报文 indev:输入设备,收到数据报的网络设备的net_device数据结构指针,即 数据报到达的接口。o 用于 NF_IP_PRE_ROUTING 和 NF_IP_LOCAL_IN 两个 HOOK outdev:输出设备,数据报离开本地所要使用的网络设备的net_device数 据结构指针。o 用于 NF_IP_LOCAL_OUT 和 NF_IP_P

20、OST_ROUTING 两个 HOOK o 注意:在通常情况下,在一次 HOOK 调用中, indev 和 outdev 中只 有一个参数会被使用 okfn:下一步要处理的函数。即如果有HOOK函数,则处理完所有的HOOK 函数,且所有向该 HOOK 注册过的筛选函数都返回 NF_ACCEPT 时,调 用这个函数继续处理;如果没有注册任何HOOK,则直接调用此函数。 其 5 个参数将由宏 NF_HOOK 传入。3. HOOK 点的实现对应于各个不同协议的不同 HOOK 点是由一个二维数组 nf_hooks 存储 的(位于 net/core/netfilter.c, Line 47),具体的 H

21、OOK 点则由数据结构 nf_hook_ops (位于 include/linux/netfilter.h, Line 44)实现。如图 所示:其中, nf_hook_ops 成员中: int priority; priority值越小,优先级越高,相关优先级在 include/linux/netfilter_ipv4.h, Line52 中枚举定义:enum NF_IP_hook_priorities NF_IP_PRI_FIRST = INT_MIN,NF_IP_PRI_CONNTRACK= -200,NF_IP_PRI_MANGLE = -150,NF_IP_PRI_NAT_DST =

22、-100,NF_IP_PRI_FILTER = 0,NF_IP_PRI_NAT_SRC = 100,NF_IP_PRI_LAST = INT_MAX,; nf_hookfn *hook; 为处理函数的指针,其函数指针类型定义位于 include/linux/netfilter.h,Line38,为:typedef unsigned int nf_hookfn(unsigned int hooknum,struct sk_buff *skb,const struct net_device *in,const struct net_device *out, int (*okfn)(struct s

23、k_buff *);这是 nf_hook_ops 中最关键的成员,其五个参数分别对应前面所解释的NF_HOOK中弟2到6个参数调用 HOOK 的包筛选函数必须返回特定的值,这些值以宏的形式定义于 头文件 include/linux/netfilter.h 中(Linel5),分别为:NF_DROP(0):丢弃此数据报,禁止包继续传递,不进入此后的处 理流程;NF_ACCEPT(1):接收此数据报,允许包继续传递,直至传递到链 表最后,而进入okfn函数;以上两个返回值最为常见NF_STOLEN(2):数据报被筛选函数截获,禁止包继续传递,但并 不释放数据报的资源,这个数据报及其占有的sk_bu

24、ff仍然有效(e.g. 将分片的数据报一一截获,然后将其装配起来再进行其他处 理);NF_QUEQUE(3):将数据报加入用户空间队列,使用户空间的程序 可以直接进行处理; 在 nf_hook_slow()以及 nf_reinject()函数(位于 net/core/netfilter.c, Line449, Line505)中,当由调用 nf_iterate() 函数(位于net/core/netfilter.c,Line339,作用为遍历所有注 册的HOOK函数,并返回相应的NF_XX值)而返回的verdict 值为NF_QUEUE时(即当前正在执行的这个HOOK筛选函 数要求将数据报加入

25、用户空间队列),会调用nf_queue()函 数(位于 net/core/netfilter.c, Line407)nf_queue()函数将这个数据报加入用户空间队列nf_info (位 于 include/linux/netfilter.h, Line77),并保存其设备信息以 备用NF_REPEAT(4):再次调用当前这个HOOK的筛选函数,进行重 复处理。4. HOOK 的注册和注销HOOK的注册和注销分别是通过nf_register_hook()函数和 nf_unregister_hook()函数(分别位于 net/core/netfilter.c,Line60,76)实现的,其 参

26、数均为一个 nf_hook_ops 结构,二者的实现也非常简单。nf_register_hook()的工作是首先遍历nf_hools,由HOOK的优先级确定 在HOOK链表中的位置,然后根据优先级将该HOOK的nf_hook_ops加入链表;nf_unregister_hook()的工作更加简单,其实就是将该HOOK的nf_hook_ops 从链表中删除。IPTables 系统1. 表规则系统IPTables 是基于 Netfilter 基本架构实现的一个可扩展的数据报高级管理系 统,利用 table、chain、rule 三级来存储数据报的各种规则。系统预定义了三个 table: filte

27、r:数据报过滤表(文件 net/ipv4/netfilter/iptable_filter.c)监听 NF_IP_LOCAL_IN、NF_IP_FORWARD 和 NF_IP_LOCAL_OUT 三个 HOOK, 作用是在所有数据报传递的关键点上对其进行过滤。 nat :网络地址转换表监听 NF_IP_PRE_ROUTING、 NF_IP_POST_ROUTING 和 NF_IP_LOCAL_OUT 三个HOOK,作用是当新连接的第一个数据报经过时,在nat表中决定对其的转 换操作;而后面的其它数据报都将根据第一个数据报的结果进行相同的转换处理 mangle:数据报修改表(位于 net/ipv

28、4/netfilter/iptable_mangle.c)监听 NF_IP_PRE_ROUTING 和 NF_IP_LOCAL_OUT 两个 HOOK,作用是修改 数据报报头中的一些值。2. 表的实现 表的基本数据结构是 ipt_tabl(e 位于 include/linux/netfilter_ipv4/ip_tables.h, Line413):struct ipt_tablestruct list_head list; / 一个双向链表char nameIPT_TABLE_MAXNAMELEN; / 被用户空间使用的表函数的名字struct ipt_replace *table; / 表

29、初始化的模板,定义了一个初始化用的该 / 表的所 默认的 HOOK 所包含的规则等信息,/ 用户通过系统调用进行表的替换时也要用unsigned int valid_hooks; /表所监听的HOOK,实质是一个位图rwlock_t lock; / 整个表的读/写自旋锁struct ipt_table_info *private; / 表所存储的数据信息,也就是实际的数据区,/ 仅在处理 ipt_table 的代码内部使用struct module *me; / 如果是模块,那么取 THIS_MODULE,否则取 NULL;其中: unsigned int valid_hooks;这个位图有两

30、个作用:一是检查Netfilter中哪些 HOOK对应着合法的entries ;二是用来为ipt_match以及ipt_target数据结 构中的checkentry()函数核算可能的HOOK。 struct module *me;当取值为 THIS_MODULE 时,可以阻止用户 rmmod 一个仍然被某个规则指向的模块的尝试。 struct ipt_replace *table;的数据结构是被用户空间用来替换一个表的,其 定义位于 include/linux/netfilter_ipv4/ip_tables.h, Line230:struct ipt_replacechar nameIPT

31、_TABLE_MAXNAMELEN;unsigned int valid_hooks;unsigned int num_entries; / 规则表入口的数量unsigned int size; / 新的规则表的总大小/* Hook entry points. */unsigned int hook_entryNF_IP_NUMHOOKS; / 表所监听 HOOK 的规则入口,/ 是对于 entries 的偏移unsigned int underflowNF_IP_NUMHOOKS; / 规则表的最大下界unsigned int num_counters; / 旧的计数器数目,即当前的旧 en

32、tries 的数目struct ipt_counters *counters; / 旧的计数器struct ipt_entry entries0; / 规则表入口; 上文所提到的 filter 、nat 和 mangle 表分别是 ipt_table 这个数据结构的三个 实例:packet_filter (位于 net/ipv4/netfilter/iptable_filter.c, Line84)、nat_table (位于 net/ipv4/netfilter/ip_nat_rule.c, Line104) 以及 packet_mangler (位 于 net/ipv4/netfilter

33、/iptable_mangle.c, Line117) ipt_table_info (位于 net/ipv4/netfilter/ip_tables.c, Line86)是实际描述规则 表的数据结构:struct ipt_table_infounsigned int size;unsigned int number; / 表项的数目unsigned int initial_entries; / 初始表项数目unsigned int hook_entryNF_IP_NUMHOOKS; / 所监听 HOOK 的规则入口unsigned int underflowNF_IP_NUMHOOKS; /

34、 规则表的最大下界char entries0 cacheline_aligned; / 规则表入口,即真正的规则存储结构 /ipt_entry组成块的起始地址,对多CPU,每个CPU对应一个;3. 规则的实现IPTables 中的规则表可以在用户空间中使用,但它所采用的数据结构与内 核空间中的是一样的,只不过有些成员不会在用户空间中使用。一个完整的规则由三个数据结构共同实现,分别是:o 一个 ipt_entry 结构,存储规则的整体信息;o 0或多个ipt_entry_match结构,存放各种match,每个结构都可以 存放任意的数据,这样也就拥有了良好的可扩展性;1 个 ipt_entry_

35、target 结构,存放规则的 target ,类似的,每个结构 也可以存放任意的数据。下面将依次对这三个数据结构进行分析:i. 存储规则整体的结构ipt_entry,其形式是一个链表(位于 include/linux/netfilter_ipv4/ip_tables.h,Line122):struct ipt_entrystruct ipt_ip ip;unsigned int nfcache;u_int16_t target_offset;u_int16_t next_offset;unsigned int comefrom;struct ipt_counters counters;uns

36、igned char elems0;其成员如下:o struct ipt_ip ip;:这是对其将要进行匹配动作的IP数据报报头的 描述,其定义于 include/linux/netfilter_ipv4/ip_tables.h, Line122, 其成员包括源/目的IP及其掩码,出入端口及其掩码,协议族、标 志/取反 flag 等信息。o unsigned int nfcache; : HOOK函数返回的cache标识,用以说明 经过这个规则后数据报的状态,其可能值有三个,定义于 include/linux/netfilter.h, Line23:#define NFC_ALTERED 0x

37、8000 /已改变 #define NFC_UNKNOWN 0x4000 /不确定另一个可能值是 0,即没有改变。o u_intl6_t target_offset;:指出了 target 的数据结构 ipt_entry_target 的起始位置,即从 ipt_entry 的起始地址到 match 存储结束的位置o u_int16_t next_offset;:指出了整条规则的大小,也就是下一条规 则的起始地址,即 ipt_entry 的起始地址到 match 偏移再到 target 存 储结束的位置o unsigned int comefrom;:所谓的“back pointer据引用此变量

38、的 代码(主要是 net/ipv4/netfilter/ip_tables.c 中)来看,它应该是指向 数据报所经历的上一个规则地址,由此实现对数据报行为的跟踪o struct ipt_counters counters;:说明了匹配这个规则的数据报的计数 以及字节计数(定义于 include/linux/netfilter_ipv4/ip_tables.h, Line100)o unsigned char elems0;:表示扩展的match开始的具体位置(因 为它是大小不确定的),当然,如果不存在扩展的match那么就是 target 的开始位置i.扩展match的存储结构ipt_entr

39、y_match,位于 include/linux/netfilter_ipv4/ip_tables.h, Line48:struct ipt_entry_match union struct u_int16_t match_size;char nameIPT_FUNCTION_MAXNAMELEN; user;struct u_int16_t match_size;struct ipt_match *match; kernel;u_int16_t match_size; /总长度 u;unsigned char data0;其中描述match大小的u_intl6_t match_size;,从

40、涉及这个变量的源码看 来,在使用的时候需要注意使用一个宏IPT_ALIGN (位于 include/linux/netfilter_ipv4/ip_tables.h, Line445)来进行 4 的对齐处理(0x3 & Oxfffffffc),这应该是由于match、target扩展后大小的不确定性决定的。在结构中,用户空间与内核空间为不同的实现,内核空间中的描述拥有 更多的信息。在用户空间中存放的仅仅是match的名称,而在内核空间中存放的 则是一个指向ipt_match结构的指针结构 ipt_match 位于 include/linux/netfilter_ipv4/ip_tables.h

41、, Line342:struct ipt_matchstruct list_head list;const char nameIPT_FUNCTION_MAXNAMELEN;int (*match)(const struct sk_buff *skb,const struct net_device *in,const struct net_device *out,const void *matchinfo, / 指向规则中 match 数据的指针,/具体是什么数据结构依情况而定int offset, / IP 数据报的偏移const void *hdr, / 指向协议头的指针u_int16_t

42、 datalen, /实际数据长度,即数据报长度-IP头长度int *hotdrop);int (*checkentry)(const char *tablename, / 可用的表const struct ipt_ip *ip,void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask); / 对应 HOOK 的位图void (*destroy)(void *matchinfo, unsigned int matchinfosize); struct module *me;其中几个重要成员:o int (*match

43、)(); :指向用该match进行匹配时的匹配函数的指针,match相关的核心实现。返回0时hotdrop置1,立即丢弃数据 报;返回非 0 表示匹配成功。o int (*checkentry)(); :当试图插入新的match表项时调用这个指针所指向的函数,对新的 match 表项进行有效性检查,即检查参 数是否合法;如果返回false,规则就不会被接受(譬如,一个TCP 的 match 只会 TCP 包,而不会接受其它)。o void (*destroy)();:当试图删除一个使用这个match的表项时,即模块释放时,调用这个指针所指向的函数。我们可以在 checkentry 中动态地分配

44、资源,并在 destroy 中将其释放。i. 扩展target的存储结构ipt_entry_target,位于 include/linux/netfilter_ipv4/ip_tables.h, Line71,这个结构与 ipt_entry_match 结构类似,同时其中描述内核空间target的结构ipt_target (位于 include/linux/netfilter_ipv4/ip_tables.h, Line375) 也与 ipt_match 类似,只 不过其中的target()函数返回值不是0/1,而是verdict。而 target 的实际使用中,是用一个结构 ipt_stan

45、dard_target 专门来描述, 这才是实际的 target 描述数据结构(位于 include/linux/netfilter_ipv4/ip_tables.h , Line94),它实际上就是一个 ipt_entry_target 加一个 verdict。 其中成员 verdict 这个变量是一个很巧妙的设计,也是一个非常重要的东 东,其值的正负有着不同的意义。我没有找到这个变量的中文名称,在内 核开发者的新闻组中称这个变量为“a magic number”。它的可能值包括 IPT_CONTINUE、IPT_RETURN 以及前文所述的 NF_DROP 等值,那么 它的作用是什么呢?o

46、 由于 IPTables 是在用户空间中执行的,也就是说 Netfilter/IPTables 这个框架需要用户态与内核态之间的数据交换以及识别。而在具体 的程序中,verdict 作为struct ipt_standard_target的一个成员,也是 对于struct ipt_entry_target中的target。函数的返回值。这个返回值 标识的是target()所对应的执行动作,包括系统的默认动作以及外 部提交的自定义动作。o但是,在用户空间中提交的数据往往是类似于“ ACCPET”之类的 字符串,在程序处理时则是以 #define NF_ACCEPT 1的形式来进 行的;而实际上,

47、以上那些执行动作是以链表的数据结构进行存储 的,在内核空间中表现为偏移。o 于是, verdict 实际上描述了两个本质相同但实现不同的值:一个是 用户空间中的执行动作,另一个则是内核空间中在链表中的偏移 而这就出现了冲突。o 解决这种冲突的方法就是:用正值表示内核中的偏移,而用负值来 表示数据报的那些默认动作,而外部提交的自定义动作则也是用正 值来表示。这样,在实际使用这个verdict时,我们就可以通过判 断值的正负来进行相应的处理了。o 位于 net/ipv4/netfilter/ip_tables.h 中的函数 ipt_do_table()中有一个典 型的verdict使用(Line3

48、35,其中v是一个verdict的实例):if (v !=IPT_RETURN) verdict = (unsigned)(-v) - 1;break;其中的 IPT_RETURN 定义为:#define IPT_RETURN (-NF_MAX_VERDICT 1)而宏NF_MAX_VERDICT实际上就是:#define NF_MAX_VERDICT NF_REPEAT这样,实际上IPT_RETURN的值就是-NF_REPEAT-1,也就是对应 REPEAT,这就是对执行动作的实际描述;而我们可以看到,在下面对verdict 进行赋值时,它所使用的值是(unsigned)(-v) - 1,这

49、就是在内核中实际对偏移进 行定位时所使用的值。那么总之呢,表和规则的实现如图 所示:从上图中不难发现, match 的定位如下:O 起始地址为:当前规则(起始)地址+ sizeof(struct ipt_entry); o结束地址为:当前规则(起始)地址+ipt_entry-target_offset; o 每一个 match 的大小为: ipt_entry_match-u.match_size。target 的定位则为:o 起始地址为 match 的结束地址,即:当前规则(起始)地址 ipt_entry- target_offset;o 结束地址为下一条规则的起始地址,即:当前规则(起始)地

50、址 ipt_entry- next_offset;o 每一个 target 的大小为: ipt_entry_target-u.target_size。这些对于理解 match 以及 target 相关函数的实现是很有必要明确的。同时,include/linux/netfilter_ipv4/ip_tables.h 中提供了三个“helper functions”可用于使对于entry、tartget和match的操作变得方便,分别是:函数ipt_get_target(): Line274,作用是取得target的起始地址,也就是上 面所说的当前规则(起始)地址+ipt_entry- targe

51、t_offset ; 宏 IPT_MATCH_ITERATE(): Line281,作用是遍历规则的所有 match, 并执行同一个(参数中)给定的函数。其参数为一个 ipt_entry_match 结构 和一个函数,以及函数需要的参数。当返回值为 0 时,表示遍历以及函数 执行顺利完成;返回非 0 值时则意味着出现问题已终止。 宏IPT_ENTRYTERATE(): Line300,作用是遍历一个表中的所有规则, 并执行同一个给定的函数。其参数为一个 ipt_entry 结构、整个规则表的 大小,以及一个函数和其所需参数。其返回值的意义与宏 IPT_MATCH_ITERATE ()类似。o

52、那么如何保证传入的 ipt_entry 结构是整个规则表的第一个结构呢? 据源码看来,实际调用这个宏的时候传入的第一个参数都是某个 ipt_table_info 结构的实例所指向的 entries 成员,这样就保证了对整 个规则表的完整遍历。4. 规则的使用当一个特定的 HOOK 被激活时,数据报就开始进入 Netfilter/IPTables 系 统进行遍历,首先检查struct ipt_ip ip,然后数据报将依次遍历各个match,也 就是struct ipt_entry_match,并执行相应的match函数,即ipt_match结构中的 *match 所指向的函数。当 match 函

53、数匹配不成功时返回 0,或者 hotdrop 被置为 1 时,遍历将会停止。对match的遍历完成后,会开始检查struct ipt_entry_target,其中如果是 一个标准的 target,那么会检查struct ipt_standard_target 中的 verdict,如果 verdict 值是正的而偏移却指向不正确的位置,那么 ipt_entry 中的 comefrom 成员就有了 用武之地数据报返回所经历的上一个规则。对于非标准的 target 呢,就会调 用target()函数,然后根据其返回值进行后面的处理。5. 规则的扩展Netfilter/IPTables提供了对规则

54、进行扩展的机制:可以写一个LKM来扩展 内核空间的功能,也可以写一个共享库来扩展用户空间中 IPTables 的功能。1. 内核的扩展要对内核空间的功能进行扩展,实际上就是写一个具有表、match以及 target 增加功能的模块,相关的函数为(位于 net/ipv4/netfilter/ip_tables.c, Line1318 to 1444): ipt_register_table()、ipt_unregister_table(),参数为 struct ipt_table *。ipt_register_table()函数是这三对函数中最复杂的一个,涉及 了内存、信号量等方方面面的东西,但

55、总起来说就做了初始 化表以及加入双向链表两件事。 其复杂一是因为涉及到多 CPU 的处理(每个 CPU 拥有各自 独立的“规则空间”),需要首先将新的 entries 放入第一 个 CPU 空间,在检查完毕后再复制到其他 CPU 中;二是就 是上面所说对新 table 各个 entry 的检查,包括边界检查以及 完整性检查等。 其中的重要函数有这么几个: translate_table()(位于 net/ipv4/netfilter/ip_tables.c, Line797):这个函数的主要作用是检查并应用用户 空间传来的规则 :1.1.1.1. 对新表进行边界检查(由宏 IPT_ENTRY_

56、ITERATE() 调用函数 check_entry_size_and_blocks(),位于 net/ipv4/netfilter/ip_tables.c , Line732) ,包括对齐、 过大过小等,特别是保证赋给 hook_entries 和 underflows 值的正确性。2. 调用函数 make_source_chains()(位于 net/ipv4/netfilter/ip_tables.c, Line499)检查新的表中 是否存在规则环,同时将 HOOK 的规则遍历顺序存 入 comefrom 变量。(这个函数我没有仔细看,只是 大概略了一下)3. 对 ipt_entry 依

57、次进行 ipt_ip 头、 match 以及 target 的 完整性检查(由宏IPT_ENTRY_ITERATE()调用函数 check_entry(),位于 net/ipv4/netfilter/ip_tables.c, Line676),保证 ipt_entry 的正确性。4. 将正确的 ipt_tables 复制给其他的 CPU。这个函数另外还在do_replace()函数(仅在一个源码中没有被调用过的函数中被 调用,不予分析)中被调用。o replace_table()(位于 net/ipv4/netfilter/ip_tables.c, Line877):这个函数的主要作用是:将得

58、到模块初 始值的ipt_table_info结构(newinfo)中的值传给 ipt_table 中的 private,并返回 ip_table 中旧的 private。 list_prepend()(位于 include/linux/netfilter_ipv4/listhelp.h, Line75):在这 个函数被调用之前,整个初始化的过程就已经结束了 这个函数的主要作用是:互斥地调用 Linux 源码中的 list_add()函数(位于 include/linux/list.h, Line55), 将新的 table 加入到双向链表之中。o ipt_register_match()、ip

59、t_unregister_match(),参数为 struct ipt_match *。o ipt_register_target()、ipt_unregister_target(),参数为 struct ipt_target *这三对函数除了 ipt_register_table()外的5个函数主要就是互斥地将 table/match/target 加入到双向链表中或者从双向链表中删除。其中向双向链表中加入新节点是通过调用list_named_insert()函数(位于 include/linux/netfilter_ipv4/listhelp.h, LinelOl)实现的。这个函数的主要工

60、作是 首先确定待插入的 match 名字是否已经存在,只有不存在时才进行插入的操作。1. 用户空间的扩展用户空间中的扩展用的是共享库配合 libiptc 库的机制,但这种机制是在 单独的 IPTbales 程序中提供的,内核源码中并没有提供,这里就不做分析了。五、数据报过滤模filter表1. 概述filter 表的功能仅仅是对数据报进行过滤,并不对数据报进行任何的修改。filter 模块在 Netfilter 中是基于下列 HOOK 点的:o NF_IP_LOCAL_INo NF_IP_FORWARDo NF_IP_LOCAL_OUT这几个 HOOK 分别对应着 filter 表中的 INP

61、UT、FORWARD、OUTPUT 三条规则链,对于任何一个数据报都会经过这 3 个 HOOK 之一。filter 模块的接口位于文件 net/ipv4/netfilter/iptables_filter.c 中。2. fil t表的定义和初始化filter 表是前面所述数据结构 ipt_table 的一个实例,它的定义和初始化位于 net/ipv4/netfilter/iptable_filter.c,Line84:static struct ipt_table packet_filter= NULL, NULL , filter, &initial_table.repl,FILTER_VA

62、LID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE ;对照结构ipt_table的定义,我们可以发现,filter表的初始化数据为: 链表初始化为空 表名为 filter 初始化的模板为& initial_table.replo 初始化的模板表定义于 net/ipv4/netfilter/iptable_filter.c, Line30,是 一个很简单的数据结构,只是赋值有些复杂,因为要对所涉及的各 个 HOOK 进行不同的处理:static structstruct ipt_replace repl;struct ipt_standard entries3;struct ipt_error term; initial_table _initdata= filter, FILTER_VALID_HOOKS, 4, sizeof(struct ipt_standard) * 3 + size

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!