Chinaunix首页 | 论坛 | 博客
  • 博客访问: 773494
  • 博文数量: 196
  • 博客积分: 115
  • 博客等级: 民兵
  • 技术积分: 354
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-13 23:19
文章分类

全部博文(196)

文章存档

2021年(1)

2019年(5)

2018年(11)

2017年(15)

2016年(13)

2015年(46)

2014年(81)

2013年(22)

2012年(2)

分类: LINUX

2014-04-28 19:20:03

        在Linux内核中数据包会有连接跟踪的功能,Linux内核根据数据包的五元组创建连接跟踪表。但对于有些数据包是不建立连接的,本篇文章介绍了ICMP的回应报文reply,就不会在内核中创建连接会话。我们知道会话的建立是在NF_IP_PRE_ROUTING的HOOK点创建。
        在ipv4_conntrack_in函数中调用了nf_conntrack_in函数对数据包进行会话的建立,其中最关键的函数是resolve_normal_ct(),在该函数中有下面一段代码:

点击(此处)折叠或打开

  1. h = nf_conntrack_find_get(net, &tuple);/*这里对会话进行查找,如果没有查找到,调用init_conntrack函数Allocate a new conntrack*/
  2.     if (!h) {
  3.         h = init_conntrack(net, &tuple, l3proto, l4proto, skb, dataoff, hooknum);
  4.         if (!h)
  5.             return NULL;
  6.         if (IS_ERR(h))
  7.             return (void *)h;
  8.     }
       在ICMP的Request请求包经过Linux内核中会创建一条会话,如果这条会话成功的存在于会话连接表中,就没有机会调用init_conntrack函数,我们看一下该函数中做对数据包做了什么处理:该函数主要是分配一个conntrack,其中有下面的代码:

点击(此处)折叠或打开

  1. if (!l4proto->new(ct, skb, dataoff)) {
  2.         nf_conntrack_free(ct);
  3.         pr_debug("init conntrack: can't track with proto module\n");
  4.         /*return NULL; */
  5.               goto ERR;
  6.     }
     如果是ICMP报文的话,调用icmp_new函数,当连接是一个新的连接时,会调用到该函数,对于Request数据报文就正常就会返回true,下面是icmp_new函数代码:

点击(此处)折叠或打开

  1. static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
  2.          unsigned int dataoff)
  3. {
  4.     static const u_int8_t valid_new[] = {
  5.         [ICMP_ECHO] = 1,
  6.         [ICMP_TIMESTAMP] = 1,
  7.         [ICMP_INFO_REQUEST] = 1,
  8.         [ICMP_ADDRESS] = 1
  9.     };

  10.     if (ct->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
  11.      || !valid_new[ct->tuplehash[0].tuple.dst.u.icmp.type]) {
  12.         /* Can't create a new ICMP `conn' with this. */
  13.         pr_debug("icmp: can't create new conn with type %u\n",
  14.              ct->tuplehash[0].tuple.dst.u.icmp.type);
  15.         nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple);
  16.         return false;
  17.     }
  18.     return true;
      在上面的代码中我们看到,在if的判断中有对连接的icmp数据包类型的判断,如果不是valid_new数组中的报文类型都会返回false,也就是数据包会在该HOOK点DROP掉。在valid_new数组中并没有ICMP_ECHOREPLY类型的报文,也就是如果是reply报文的话,这里会被直接的DROP掉。所以在REQUEST数据包通过该HOOK点是,创建一条连接同时也会创建一条反方向的连接,所以,当REPLY报文被收到时,正常情况下会查找到相应的连接会话,也就是h = nf_conntrack_find_get(net, &tuple);函数返回的h不为空。因此,对于reply报文是不会重新创建会话的,如果ICMP的REPLY报文走到icmp_new函数处,说明ICMP的REQUEST会话并没有被创建,在查找会话时失败,同时造成了ICMP数据包不通的问题。



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