Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15665
  • 博文数量: 7
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2017-04-10 19:30
文章分类

全部博文(7)

文章存档

2015年(7)

我的朋友

分类: LINUX

2015-01-29 20:42:33

1. 什么是连接跟踪
    连接跟踪(CONNTRACK),跟踪并且记录连接状态。Linux为每一个经过网络堆栈的数据包,生成一个新的连接记录项(Connection entry)。此后,所有属于此连接的数据包都被唯一地分配给这个连接,并标识连接的状态。连接跟踪是防火墙模块的状态检测的基础,同时也是地址转换中实现SNAT和DNAT的前提。 
那么Netfilter又是如何生成连接记录项的呢?每一个数据,都有“来源”与“目的”主机,发起连接的主机称为“来源”,响应“来源”的请求的主机即为目的,所谓生成记录项,就是对每一个这样的连接的产生、传输及终止进行跟踪记录。由所有记录项产生的表,即称为连接跟踪表。 (摘自:独孤九贱博文)

2为什么需要连接跟踪功能
     连接跟踪状态防火墙NAT的实现基础。

3. 连接跟踪是如何起作用的(linux.2.6.36.x)
    1)连接跟踪和netfilter中注册的hook点
    
上述图片为协议栈流程图,ipv4协议的五个hook监测点。其对应的ip_conntract_hook如下图:
 
我们以IPV4协议为例查看部分代码:

点击(此处)折叠或打开

  1. static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
  2.     {
  3.         .hook        = ipv4_conntrack_in,
  4.         .owner        = THIS_MODULE,
  5.         .pf        = NFPROTO_IPV4,
  6.         .hooknum    = NF_INET_PRE_ROUTING,
  7.         .priority    = NF_IP_PRI_CONNTRACK,
  8.     },
  9.     {
  10.         .hook        = ipv4_conntrack_local,
  11.         .owner        = THIS_MODULE,
  12.         .pf        = NFPROTO_IPV4,
  13.         .hooknum    = NF_INET_LOCAL_OUT,
  14.         .priority    = NF_IP_PRI_CONNTRACK,
  15.     },
  16.     {
  17.         .hook        = ipv4_confirm,
  18.         .owner        = THIS_MODULE,
  19.         .pf        = NFPROTO_IPV4,
  20.         .hooknum    = NF_INET_POST_ROUTING,
  21.         .priority    = NF_IP_PRI_CONNTRACK_CONFIRM,
  22.     },
  23.     {
  24.         .hook        = ipv4_confirm,
  25.         .owner        = THIS_MODULE,
  26.         .pf        = NFPROTO_IPV4,
  27.         .hooknum    = NF_INET_LOCAL_IN,
  28.         .priority    = NF_IP_PRI_CONNTRACK_CONFIRM,
  29.     },
  30. };
以ipv4_conntract_local为例:

点击(此处)折叠或打开

  1. static unsigned int ipv4_conntrack_local(unsigned int hooknum,
  2.                      struct sk_buff *skb,
  3.                      const struct net_device *in,
  4.                      const struct net_device *out,
  5.                      int (*okfn)(struct sk_buff *))
  6. {
  7.     /* root is playing with raw sockets. */
  8.     if (skb->len < sizeof(struct iphdr) ||
  9.      ip_hdrlen(skb) < sizeof(struct iphdr))
  10.         return NF_ACCEPT;
  11.     return nf_conntrack_in(dev_net(out), PF_INET, hooknum, skb);
  12. }
在hook监测点hook操作函数调用nf_conntrack_in函数,进入连接跟踪。                                                                                 

    2)连接跟踪的三条路径
     由上图可知,每个数据包路径无非是三种路径的一种,他们分别是:转发的包;本地接收的包;本地发送的包。
     转发:

    本地接收

    本地发送
                                                                                           
     3)本地发包和接收包的路径   
        本地发包:
    IP层发送数据包(TCP包)的函数为:
    ip_queue_xmit()         // ip_output.c
    执行到最后调用 res = ip_local_out(skb);  --> __ip_local_out(skb); --> 
    return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL,
      skb_dst(skb)->dev, dst_output);
执行所有NF_INET_LOCAL_OUT上的勾子,仅当所有钩子函数都返回NF_ACCEPT,接着执行 dst_output。所以会执行ipv4_conntrack_local();                                                                                             
ipv4_conntrack_local() --> nf_conntrack_in() -->     nf_ct_put() -->              -->  ipv4_confirm() --> nf_conntrack_confirm()                

    本地接收包:
    ip_rcv()        // ip_input.c
    最后执行:return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL,
      ip_rcv_finish);
执行所有NF_INET_PRE_ROUTING上的钩子,仅当所有钩子函数都返回NF_ACCEPT,接着执行 ip_rcv_finish。所以会执行ipv4_conntrack_in();               
                     
    
    本文所有:Devile May Cry J        QQ:384668960  
阅读(769) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~