Netfilter分析(1)

1310阅读 0评论2015-12-02 qxhgd
分类:LINUX

    本来听说Linux网络代码是最杂乱的,很容易陷进去却出不来,但这几天做了一阵子Netfilter的代码分析,发现Linux网络部分并没有那么可怕。。。

    看Netfilter的最大收获可以说就是无意中找到了一个切入Linux网络代码的绝佳架构——拿IPv4为例子,以Netfilter为引,很容易地就能够迅速遍历整个IP数据报地处理流程,而对整个框架有了一个整体地印象之后,无论是更加详细的深入分析还是需要寻找某个具体实现的位置,就都是很轻松的了。

    下面是这三四天里我看Netfilter代码的一些初步收获:

Netfilter分析(1)

1、 Netfilter/IPTables框架简介

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

2、 主要源代码文件:

3、 Netfilter/IPTables-IPv4总体架构

    Netfilter主要通过表、链实现规则,可以这么说,NetFilter是表的容器,表是链的容器,链是规则的容器,最终形成对数据报处理规则的实现。
    详细地说,Netfilter/IPTables的体系结构可以分为两个大部分:

1. Netfilter的HOOK机制

    Netfilter的通用框架不依赖于具体的协议,而是为每种网络协议定义一套HOOK 函数。这些HOOK函数在数据报经过协议栈的几个关键点时被调用,在这几个点中,协议栈将数据报及 HOOK函数标号作为参数,传递给Netfilter框架。
    对于它在网络堆栈中增加的这些HOOK,内核的任何模块可以对每种协议的一个或多个HOOK进行注册,实现挂接。这样当某个数据报被传递给 Netfilter框架时,内核能检测到是否有任何模块对该协议和HOOK函数进行了注册。若注册了,则调用该模块的注册时使用的回调函数,这样这些模块就有机会检查、修改、丢弃该数据报及指示Netfilter将该数据报传入用户空间的队列。
    这样,HOOK提供了一种方便的机制:在数据报通过Linux内核的不同位置上截获和操作处理数据报。

2. IPTables基础模块

    IPTables基础模块实现了三个表来筛选各种数据报,具体地讲,Linux2.4内核提供的这三种数据报的处理功能是相互间独立的模块,都基于Netfilter的HOOK函数和各种表、链实现。如图06-10-20-1所示(不知为什么图片传上来预览却看不到,先暂时放在相册里了,用OpenOffice画的,在Windows下转过来后画质差了好多。。。-_-!)(如果哪位大大知道怎么在文章里搞定图片,麻烦告偶一声哦)

    另外,Netfilter/IPTables还提供了连接跟踪的实现,也是一个相当重要的模块。

4、 HOOK的实现

1. Netfilter-IPv4中的HOOK:

    Netfilter模块需要使用HOOK来启用函数的动态钩接,它在IPv4中定义了五个 HOOK(位于文件include/linux/netfilter_ipv4.h,Line 39),分别对应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_LOCAL_OUT 处理后,进行路由选择处理,然后经过NF_IP_POST_ROUTING处理后发送出去。
    总之,这五个HOOK所组成的Netfilter-IPv4数据报筛选体系如图06- 10-20-2所示(注:下面所说Netfilter/IPTables均基于IPv4,不再赘述)

    详细地说,各个HOOK及其在IP数据报传递中的位置如下:(见图06-10-20-3— —有了这个整体的印象之后,再去看网络代码,至少第3层的代码,是不是就好多了。。。当然,这个图也不是很完整,像IP报文分割啦,多播啦之类的都没有画进去,因为那些跟我们Netfilter的主题没什么关系。。。)

    其中,在06-10-20-3这个体系图中,下面两个函数相当于IP协议栈与链路层的接口:

2. HOOK的调用

    HOOK的调用是通过宏NF_HOOK实现的,其定义位于include/linux/netfilter.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()函数(位于net/core/netfilter.c,Line449)的工作主要是读nf_hook数组遍历所有的nf_hook_ops结构,并调用nf_hookfn()处理各个数据报。
    即HOOK的调用过程如图06-10-20-4所示:

下面说明一下NF_HOOK的各个参数:

#define PACKET_HOST  0 /* 发送到本机的报文*/
#define PACKET_BROADCAST 1 /* 广播报文*/
#define PACKET_MULTICAST 2 /* 多播报文*/
#define PACKET_OTHERHOST 3 /* 表示目的地非本机但被本机接收的报文*/
#define PACKET_OUTGOING  4 /* 离开本机的报文 */
/* These ones are invisible by user level */
#define PACKET_LOOPBACK  5 /* 本机发给自己的报文 */
#define PACKET_FASTROUTE 6 /* 快速路由报文*/

3. HOOK点的实现

    对应于各个不同协议的不同HOOK点是由一个二维数组nf_hooks存储的(位于 net/core/netfilter.c,Line 47),具体的HOOK点则由数据结构nf_hook_ops(位于 include/linux/netfilter.h,Line 44)实现。如图06-10-20-5所示

    其中,nf_hook_ops成员中:

 

 

 

 
上一篇:Netfilter分析(2)
下一篇:Netfilter连接跟踪状态解析