Chinaunix首页 | 论坛 | 博客
  • 博客访问: 273846
  • 博文数量: 72
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 276
  • 用 户 组: 普通用户
  • 注册时间: 2014-07-28 23:52
文章分类

全部博文(72)

文章存档

2017年(20)

2014年(52)

分类: LINUX

2014-10-16 16:56:25

经过上面一些辅助功能实现的分析,现在我们终于可以来分析conntrack的核心实现了。

 

conntrack 也是通过Netfilterhook机制,在相应的点上拦截报文,进行相应的conntrack的建立和处理。

我们先来看看IPv4 Netfilter中各个模块的hook点分布。
下图的创意是我在网上的一篇博文里借鉴过来的(原文地址http://blog.chinaunix.net/uid-23069658-id-3162264.html)。

从上图我们可以看出各个模块注册的hook点及其他们的优先级。

1、因为conntrack是要分析报文的L4层信息,所有conntrack就无法处理ip分片报文的后续片报文。因此,如果打开了ip conntrack功能,conntrack模块就会在netfilter入口对ip分片报文进行重组,重组后再进行处理。

 

IP conntrack以最高优先级在Netfilter的入口处注册了hook函数,来进行IP分片报文的重组。

 

2、在Netfilter的入口点,conntrack会拦截报文,查找已建立的conntrack和报文进行关联,如果conntrack没有建立,就新建conntrack

 

3、在Netfilter的出口点,conntrack拦截报文,对已经建立的conntrack的状态进行确认和更新。


net/ipv4/netfilter/nf_defrag_ipv4.c

static struct nf_hook_ops ipv4_defrag_ops[] = {

    {

        .hook = ipv4_conntrack_defrag,

        .owner = THIS_MODULE,

        .pf = PF_INET,

        .hooknum = NF_INET_PRE_ROUTING,

        .priority = NF_IP_PRI_CONNTRACK_DEFRAG,

    },

    {

        .hook           = ipv4_conntrack_defrag,

        .owner          = THIS_MODULE,

        .pf             = PF_INET,

        .hooknum        = NF_INET_LOCAL_OUT,

        .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,

    },

};

IPv4分片报文进行分片重组的代码我们这里就不进行分析了,大家知道conntrack会对所有进入NetfilterIPv4分片报文进行重组即可。

 

 

net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c

static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {

//入口

    {

        .hook = ipv4_conntrack_in,

        .owner = THIS_MODULE,

        .pf = NFPROTO_IPV4,

        .hooknum = NF_INET_PRE_ROUTING,

        .priority = NF_IP_PRI_CONNTRACK,

    },

    {

        .hook = ipv4_conntrack_local,

        .owner = THIS_MODULE,

        .pf = NFPROTO_IPV4,

        .hooknum = NF_INET_LOCAL_OUT,

        .priority = NF_IP_PRI_CONNTRACK,

    },
    //出口

    {

        .hook = ipv4_confirm,

        .owner = THIS_MODULE,

        .pf = NFPROTO_IPV4,

        .hooknum = NF_INET_POST_ROUTING,

        .priority = NF_IP_PRI_CONNTRACK_CONFIRM,

    },

    {

        .hook = ipv4_confirm,

        .owner = THIS_MODULE,

        .pf = NFPROTO_IPV4,

        .hooknum = NF_INET_LOCAL_IN,

        .priority = NF_IP_PRI_CONNTRACK_CONFIRM,

    },

};

 

 

我们看一看Netfilter中入口对报文的处理:

static unsigned int ipv4_conntrack_in(unsigned int hooknum,

      struct sk_buff *skb,

      const struct net_device *in,

      const struct net_device *out,

      int (*okfn)(struct sk_buff *))

{

    return nf_conntrack_in(dev_net(in), PF_INET, hooknum, skb);

}

static unsigned int ipv4_conntrack_local(unsigned int hooknum,

                                                             struct sk_buff *skb,

                                                             const struct net_device *in,

                                                             const struct net_device *out,

                                                             int (*okfn)(struct sk_buff *))

{

    /* root is playing with raw sockets. */

    if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr))

        return NF_ACCEPT;

    return nf_conntrack_in(dev_net(out), PF_INET, hooknum, skb);

}

两个函数最后到调用了nf_conntrack_in来处理报文。

 

Netfilter中出口对报文的处理都是调用了ipv4_confirm来处理报文。

(未完待续)




阅读(2064) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~