NetFilter (2)

        上一篇文章中,我们已经知道如何得到对数据包的控制。那么 NetFilter 是如何组织规则来处理经过的数据包呢?

        我们知道在用户层的防火墙配置工具 iptables 中,有四个表五条链的说法,五条链其实就是上一篇中讲到的五个不同的拦截点,那四个表呢,分表中 Filter, Nat, Mangle, Raw,从名字上就可以看出它们的作用,这里不讲,也就是说,当你添加包的匹配规则时,需要指定添加到哪张表的哪个拦截点上,当然并不是所有的表都支持所有的拦截点,下图是它们各自支持的拦截点的对应关系:

技术分享

        添加规则时需要指出哪张表的哪个拦截点,这其实也是 NetFilter 在内核中组织匹配规则的方式,我们首先看一下整个 NetFilter 存储规则的结构:

技术分享

        (图解,图中的虚线箭头表示将上一个结构体的部分放大。实线代表指针。)

        从上图中,可以清晰地看到,在网络的命令空间中, xt 指向一个表的数组,它包括所有网络类型的表的链表头,其中 AF_INET 表示 Internet 防火墙,也就是 NetFilter 中所有的表的链表头,当然网络系统中的代码足够灵活,它提供了接口来注册表,

struct xt_table *xt_register_table(struct net *net, struct xt_table *table,
				   struct xt_table_info *bootstrap,
				   struct xt_table_info *newinfo)
        每个表的规则,则存储在 xt_table.private 中,它是一个 xt_table_info 的结构体,而后者存储了该表中的所有匹配规则。某张表的所有规则是存放在一块连续内存中的,由于每个表都可能有五个拦截点,所以 hook_entry 记录了所有拦截中规则的偏移,而 entries 则给出了所有规则的起始地址,这样,想要查找某个拦截点配置的规则,就可以通过 base + offset 的得到该拦截点的规则了。
        规则的组织是由 ipt_standard 来表示,其中 entry 表示匹配方法,target 表示所采取的处理方式,由于支持扩展规则,所以规则的长度是不定的,所以每个规则,需要指出自己的大小,以及下一条规则的偏移,这就是我们看到的 ipt_entry 的结构,这样,遍历规则时就可以很方便地进行了,在不同防火墙解析时,就可以添加上自己的扩展匹配,ipt_entry 的 elems 就是匹配的数据部分,代码中会给出详细的处理过程,当匹配完某一规则后,根据 ipt_entry.next_offset 就可以找到下一条规则了,这样整个匹配过程就可以依次处理。
        其实整个上面的流程,就是我们在拦截点得到 ip 包处理机会后,查找整个匹配以及处理的过程,顺着这样的思路很容易看懂整个代码框架。
        在 ipv4 的 NetFilter 实现中,不同表的注册拦截操作是在相同名称的代码中实现的,即 filter 表是由 iptable_filter.c 来完成拦截注册的,我们以 OUTPUT 拦截点为例,它的注册回调函数是 ipt_local_out_hook ,当数据包发送时,ipt_local_out_hook 会被调用,它会调用 ipt_do_table 在相应的表中查找匹配规则,ipt_do_table 就会根据上面讲到的原理,来依次遍历匹配规则。这样就可以实现防火墙的功能了。
        那么剩下最后一个问题,用户态的配置规则如何传递给内核态的,简单来说,它是通过 

#include <sys/types.h>          
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
        来进行通信的,为了便于扩展,它只定义了框架,每个防火墙定义自己的 get 和 set 方法,ipv4 则调用 nf_register_sockopt(&ipt_sockopts) 来完成这两个函数的注册,这样就可以完成自己规则的配置工作了。
        当知道了 NetFilter 的原理之后,我相信,NetFilter 的代码已经很容易地被阅读了。 (完)

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。