Netfilter框架完全解析.docx

上传人:b****4 文档编号:3120535 上传时间:2022-11-17 格式:DOCX 页数:26 大小:1.04MB
下载 相关 举报
Netfilter框架完全解析.docx_第1页
第1页 / 共26页
Netfilter框架完全解析.docx_第2页
第2页 / 共26页
Netfilter框架完全解析.docx_第3页
第3页 / 共26页
Netfilter框架完全解析.docx_第4页
第4页 / 共26页
Netfilter框架完全解析.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

Netfilter框架完全解析.docx

《Netfilter框架完全解析.docx》由会员分享,可在线阅读,更多相关《Netfilter框架完全解析.docx(26页珍藏版)》请在冰豆网上搜索。

Netfilter框架完全解析.docx

Netfilter框架完全解析

Netfilter框架

目录

1网络通信

1.1网络通信的基本模型

1.2协议栈底层机制

2Netfilter

2.1Netfilter介绍

2.2钩子函数返回值

2.3hook点

2.4协议栈切入Netfilter框架

3Netfilter的实现方式

3.1nf_hooks[][]结构

3.2nf_hook_ops

3.3增加新的钩子函数

3.4基于源接口的数据包过滤钩子函数

4iptables防火墙内核模块

4.1iptables

4.2Netfilter框架防火墙iptableshook函数分类

4.3iptables基础

4.4iptables命令格式

5连接跟踪机制

5.1.重要数据结构

5.2重要函数

5.3链接跟踪建立的三条路径

5.4IP层接收和发送数据包进入连接跟踪钩子函数的入口

5.5连接跟踪的流程分析

1网络通信

1.1网络通信的基本模型

在数据的发送过程中,从上至下依次是“加头”的过程,每到达一层数据就被会加上该层的头部;与此同时,接受数据方就是个“剥头”的过程,从网卡收上包来之后,在往协议栈的上层传递过程中依次剥去每层的头部,最终到达用户那儿的就是裸数据了。

1.2协议栈底层机制

“栈”模式底层机制基本就是像下面这个样子:

对于收到的每个数据包,都从“A”点进来,经过路由判决,如果是发送给本机的就经过“B”点,然后往协议栈的上层继续传递;否则,如果该数据包的目的地是不本机,那么就经过“C”点,然后顺着“E”点将该包转发出去。

对于发送的每个数据包,首先也有一个路由判决,以确定该包是从哪个接口出去,然后经过“D”点,最后也是顺着“E”点将该包发送出去。

协议栈五个关键点A,B,C,D和E就是我们Netfilter大展拳脚的地方了。

2Netfilter

2.1Netfilter介绍

Netfilter是Linux2.4.x引入的一个子系统,它作为一个通用的、抽象的框架,提供一整套的hook函数的管理机制,使得诸如数据包过滤、网络地址转换(NAT)和基于协议类型的连接跟踪成为了可能。

Netfilter在内核中位置如下图所示:

这幅图,很直观的反应了用户空间的iptables和内核空间的基于Netfilter的ip_tables模块之间的关系和其通讯方式,以及Netfilter在这其中所扮演的角色。

Netfilter在netfilter_ipv4.h中将那五个关键点“ABCDE”上来。

重新命名,如下图所示。

2.2钩子函数返回值

在每个关键点上,有很多已经按照优先级预先注册了的回调函数(这些函数称为“钩子函数”)埋伏在这些关键点,形成了一条链。

对于每个到来的数据包会依次被那些回调函数“调戏”一番再视情况是将其放行,丢弃还是怎么滴。

但是无论如何,这些回调函数最后必须向Netfilter报告一下该数据包的死活情况,因为毕竟每个数据包都是Netfilter从人家协议栈那儿借调过来给兄弟们Happy的,别个再怎么滴也总得“活要见人,死要见尸”吧。

每个钩子函数最后必须向Netfilter框架返回下列几个值其中之一:

nNF_ACCEPT继续正常传输数据报。

这个返回值告诉Netfilter:

到目前为止,该数据包还是被接受的并且该数据包应当被递交到网络协议栈的下一个阶段。

nNF_DROP丢弃该数据报,不再传输。

nNF_STOLEN模块接管该数据报,告诉Netfilter“忘掉”该数据报。

该回调函数将从此开始对数据包的处理,并且Netfilter应当放弃对该数据包做任何的处理。

但是,这并不意味着该数据包的资源已经被释放。

这个数据包以及它独自的sk_buff数据结构仍然有效,只是回调函数从Netfilter获取了该数据包的所有权。

nNF_QUEUE对该数据报进行排队(通常用于将数据报给用户空间的进程进行处理)

nNF_REPEAT再次调用该回调函数,应当谨慎使用这个值,以免造成死循环。

上面提到的五个关键点后面我们就叫它们为hook点,每个hook点所注册的那些回调函数都将其称为hook函数。

2.3hook点

Linux2.6版内核的Netfilter目前支持IPv4、IPv6以及DECnet等协议栈,这里我们主要研究IPv4协议。

关于协议类型,hook点,hook函数,优先级,通过下面这个图给大家做个详细展示:

对于每种类型的协议,数据包都会依次按照hook点的方向进行传输,每个hook点上Netfilter又按照优先级挂了很多hook函数。

这些hook函数就是用来处理数据包用的。

Netfilter使用NF_HOOK(include/linux/netfilter.h)宏在协议栈内部切入到Netfilter框架中。

相比于2.4版本,2.6版内核在该宏的定义上显得更加灵活一些,定义如下:

#defineNF_HOOK(pf,hook,skb,indev,outdev,okfn)\

NF_HOOK_THRESH(pf,hook,skb,indev,outdev,okfn,INT_MIN)

关于宏NF_HOOK各个参数的解释说明:

1)pf:

协议族名,Netfilter架构同样可以用于IP层之外,因此这个变量还可以有诸如PF_INET6,PF_DECnet等名字。

2)hook:

HOOK点的名字,对于IP层,就是取上面的五个值;

3)skb:

不解释;

4)indev:

数据包进来的设备,以structnet_device结构表示;

5)outdev:

数据包出去的设备,以structnet_device结构表示;

(后面可以看到,以上五个参数将传递给nf_register_hook中注册的处理函数。

6)okfn:

是个函数指针,当所有的该HOOK点的所有登记函数调用完后,转而走此流程。

NF_HOOK_THRESH又是一个宏:

#defineNF_HOOK_THRESH(pf,hook,skb,indev,outdev,okfn,thresh)

我们发现NF_HOOK_THRESH宏只增加了一个thresh参数,这个参数就是用来指定通过该宏去遍历钩子函数时的优先级,同时,该宏内部又调用了nf_hook_thresh函数:

这个函数又只增加了一个参数cond,该参数为0则放弃遍历,并且也不执行okfn函数;为1则执行nf_hook_slow去完成钩子函数okfn的顺序遍历(优先级从小到大依次执行)。

在net/netfilter/core.h文件中定义了一个二维的结构体数组,用来存储不同协议栈钩子点的回调处理函数。

structlist_headnf_hooks[NPROTO][NF_MAX_HOOKS];

其中,行数NPROTO为32,即目前内核所支持的最大协议簇;列数NF_MAX_HOOKS为挂载点的个数,目前在2.6内核中该值为8。

nf_hooks数组的最终结构如下图所示。

在include/linux/socket.h中IP协议AF_INET(PF_INET)的序号为2,因此我们就可以得到TCP/IP协议族的钩子函数挂载点为:

PRE_ROUTING:

nf_hooks[2][0]

LOCAL_IN:

nf_hooks[2][1]

NF_IP_FOWARDnf_hooks[2][2]

LOCAL_OUT:

nf_hooks[2][3]

POST_ROUTING:

nf_hooks[2][4]

2.4协议栈切入Netfilter框架

在2.6内核的IP协议栈里,从协议栈正常的流程切入到Netfilter框架中,然后顺序、依次去调用每个HOOK点所有的钩子函数的相关操作有如下几处:

1)、net/ipv4/ip_input.c里的ip_rcv函数。

该函数主要用来处理网络层的IP报文的入口函数,它到Netfilter框架的切入点为:

NF_HOOK(PF_INET,NF_IP_PRE_ROUTING,skb,dev,NULL,ip_rcv_finish)

根据前面的理解,这句代码意义已经很直观明确了。

那就是:

如果协议栈当前收到了一个IP报文(PF_INET),那么就把这个报文传到Netfilter的NF_IP_PRE_ROUTING过滤点,去检查[R]在那个过滤点(nf_hooks[2][0])是否已经有人注册了相关的用于处理数据包的钩子函数。

如果有,则挨个去遍历链表nf_hooks[2][0]去寻找匹配的match和相应的target,根据返回到Netfilter框架中的值来进一步决定该如何处理该数据包(由钩子模块处理还是交由ip_rcv_finish函数继续处理)。

[R]:

刚才说到所谓的“检查”。

其核心就是nf_hook_slow()函数。

该函数本质上做的事情很简单,根据优先级查找双向链表nf_hooks[][],找到对应的回调函数来处理数据包:

structlist_head**i;

list_for_each_continue_rcu(*i,head){

structnf_hook_ops*elem=(structnf_hook_ops*)*i;

if(hook_thresh>elem->priority)

continue;

verdict=elem->hook(hook,skb,indev,outdev,okfn);

if(verdict!

=NF_ACCEPT){……}

returnNF_ACCEPT;

}

上面的代码是net/netfilter/core.c中的nf_iterate()函数的部分核心代码,该函数被nf_hook_slow函数所调用,然后根据其返回值做进一步处理。

2)、net/ipv4/ip_forward.c中的ip_forward函数,它的切入点为:

NF_HOOK(PF_INET,NF_IP_FORWARD,skb,skb->dev,rt->u.dst.dev,ip_forward_finish);

在经过路由抉择后,所有需要本机转发的报文都会交由ip_forward函数进行处理。

这里,该函数由NF_IP_FOWARD过滤点切入到Netfilter框架,在nf_hooks[2][2]过滤点执行匹配查找。

最后根据返回值来确定ip_forward_finish函数的执行情况。

3)、net/ipv4/ip_output.c中的ip_output函数,它切入Netfilter框架的形式为:

NF_HOOK_COND(PF_INET,NF_IP_POST_ROUTING,skb,NULL,dev,ip_finish_output,

!

(IPCB(skb)->flags&IPSKB_REROUTED));

这里我们看到切入点从无条件宏NF_HOOK改成了有条件宏NF_HOOK_COND,调用该宏的条件是:

如果协议栈当前所处理的数据包skb中没有重新路由的标记,数据包才会进入Netfilter框架。

否则直接调用ip_finish_output函数走协议栈去处理。

除此之外,有条件宏和无条件宏再无其他任何差异。

如果需要陷入Netfilter框架则数据包会在nf_hooks[2][4]过滤点去进行匹配查找。

4)、还是在net/ipv4/ip_input.c中的ip_local_deliver函数。

该函数处理所有目的地址是本机的数据包,其切入函数为:

NF_HOOK(PF_INET,NF_IP_LOCAL_IN,skb,skb->dev,NULL,ip_local_deliver_fi

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1