热门关键字:  ubuntu  分区  Fedora  linux系统进程  函数

当前位置 :| 主页>Linux教程>内核研究>

Linux netfilter机制应用浅释

来源: 作者: 时间:2008-10-17 Tag: 点击:
   Netfilter是自2.2版本内核后Linux网络内核重要的组成部分,是Linux网络防火墙以及IPtable实现的基础。Netfilter是一个提供了不同于BSD Socket接口的操作网络数据包的机制。在Netfilter中,协议栈每种协议都定义了若干个钩子(HOOK),如IPv6和IP v4均定义了五个钩子(将在后面的章节中详解),而对应协议的数据包将按照一定的规则通过若干个钩子,每一个钩子都是处理函数挂载点。内核模块则可以在各个钩子上注册处理函数,以操作经过对应钩子的数据包。函数处理后,根据一定的策略返回给内核进行下一步的处理。下面我们一IPv6为例子作进一步的解释。
    IPv6协议定义了一下五个钩子,它们的名字(名字后面的是它们对应的值)告诉我们它们所处的位置,如图所示:

    1. NF_IP6_PRE_ROUTING 0:数据包在抵达路由之前经过这个钩子。目前,在这个钩子上只对数据包作包头检测处理,一般应用于防止拒绝服务攻击和NAT;
    2. NF_IP6_LOCAL_IN 1:目的地为本地主机的数据包经过这个钩子。防火墙一般建立在这个钩子上;
    3. NF_IP6_FORWARD 2:目的地非本地主机的数据包经过这个钩子;
    4. NF_IP6_LOCAL_OUT 3:本地主机发出的数据包经过这个钩子;
    5. NF_IP6_POST_ROUTING 4:数据包在离开本地主机之前经过这个钩子,包括源地址为本地主机和非本地主机的。
    对照图片,我们分析数据报经过Netfilter机制的过程。数据报从左边进入系统,进行IP校验以后,数据报经过第一个钩子 NF_IP6_PRE_ROUTING注册函数进行处理;然后就进入路由代码,其决定该数据包是需要转发还是发给本机的;若该数据包是发被本机的,则该数据经过钩子NF_IP6_LOCAL_IN注册函数处理以后然后传递给上层协议;若该数据包应该被转发则它被NF_IP6_FORWARD注册函数处理;经过转发的数据报经过最后一个钩子NF_IP6_POST_ROUTING注册函数处理以后,再传输到网络上。
    本地产生的数据经过钩子函数NF_IP6_LOCAL_OUT注册函数处理以后,进行路由选择处理,然后经过NF_IP6_POST_ROUTING注册函数处理以后发送到网络上。
    注册函数处理完后,将返回一个整形常量,内核根据这个返回值随数据报作下一步的处理。目前内核定义了一下四个常量:
        1. NF_DROP 0:丢弃此数据报,而不进入此后的处理;
        2. NF_ACCEPT 1:接受此数据报,进入下一步的处理;
        3. NF_STOLEN 2:表示异常分组;
        4. NF_QUEUE 3:排队到用户空间,等待用户处理;
        5. NF_REPEAT 4:进入此函数再作处理。
    为了是其它内核模块能够操作数据报,Netfilter为我们提供了接口nf_register_hook(struct nf_hook_ops *reg),函数原型在netfilter.h,定义在netfilter.c,返回值为int类型,注册成功返回零,失败则返回一个负值,参数reg为 nf_hook_ops结构体类型指针。我们在内核模块初始化的时候调用这个接口来注册处理函数,而我们的函数指针则保存在reg指针所指向的 nf_hook_ops。nf_hook_ops定义在netfilter.h:
        struct nf_hook_ops
        {
            struct list_head list;
            nf_hookfn *hook;
            int pf;
            int hooknum;
            int priority;
        };
        list:链表头,用来把各个处理函数组织成一个表,初始化为{NULL,NULL};
        hook:我们定义的处理函数的指针,返回值必须为前面所说的几个常量之一;
        pf:协议族,表示这个HOOK属于哪个协议族;
        hooknum:我们想要注册的钩子,取值为五个钩子之一;
        priority:优先级,目前Netfilter定义了一下几个优先级,取值也小优先级也高,我们可以根据需要对各个优先级加减一个常量得到符合我们需要的优先级。
 
        NF_IP6_PRI_FIRST = INT_MIN
        NF_IP6_PRI_CONNTRACK = -200
        NF_IP6_PRI_MANGLE = -150
        NF_IP6_PRI_NAT_DST = -100
        NF_IP6_PRI_FILTER = 0
        NF_IP6_PRI_NAT_SRC = 100
        NF_IP6_PRI_LAST = INT_MAX
    接下来我们谈谈处理函数的定义,函数指针的类型为nf_hookfn,它的定义为:
        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 sk_buff *));
    所有的这些参数都是由Netfilter传递给我们的处理函数的。除了okfn其它用途都比较易懂,okfn是当对应的钩子的注册函数为空时, Netfilter调用的处理函数,它就是如果我们的处理函数返回Accept时Netfilter调用的处理函数。


相关文章:
精通initramfs构建step by step
Linux利用kexec迅速切换内核
进程上下文VS中断上下文
内核通知链 学习笔记
linux spi子系统驱动分析
menuconfig 配置选项
《Linux操作系统内核实习》之练习一
udev详解
什么叫微内核,宏内核?
Linux 信号signal处理机制
开发简单的 Linux2.6 内核模块
删除内核的perl脚本
Linux2.6内核usb gadget驱动移植
GCC hacks in the Linux kernel
iomem
kernel学习的想法
让自己的驱动支持udev
linux内核编译步骤
内核的等待队列
Linux内核wait_queue深入分析
升级和删除内核
SD卡驱动分析2
Linux Kernel VDSO本地权限提升漏洞
内核中的TCP的追踪分析-15-TCP(IPV4)的客户端与
linux 2.6内核可加载模块的编译
内核模块HelloWorld
在环回接口上发送一个数据报
ARP初始化
1分钟编译FreeBSD内核
linux设备模型之uart驱动架构分析