linux开发专注者(坚持原创)linuxfocus.blog.chinaunix.net

多阅读,多思考,多实践,多分享!

  • 博客访问: 5183930
  • 博文数量: 238
  • 博客积分: 10424
  • 博客等级: 少将
  • 技术积分: 14180
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-14 12:45
  • 认证徽章:
个人简介

啦啦啦~~~

文章分类

全部博文(238)

文章存档

2015年(5)

2014年(2)

2013年(22)

2012年(67)

2011年(120)

2010年(22)

微信关注

IT168企业级官微



微信号:IT168qiye



系统架构师大会



微信号:SACC2013

订阅
热词专题
Netfilter连接跟踪状态解析 2015-08-18 22:53:17

分类: LINUX

<p> 作者:gfree.wind@gmail.com<br /> 博客:linuxfocus.blog.chinaunix.net<br /> 微博:weibo.com/glinuxer<br /> QQ技术群:4367710<br /> github:https://github.com/gfreewind&nbsp;&nbsp; <br /> </p> <h2> 背景介绍 </h2> <p> Netfilter是Linux防火墙内核部分的实现,其对应的用户空间工具即大名鼎鼎的iptables。 由于Netfilter代码及框架具有非常好的扩展性,所以很多中小公司都是基于Netfilter进行二次开发,即使其性能不是特别理想——这是由 Netfilter自身的设计决定的。<br /> 连接跟踪是状态防火墙或者七层网关的基础。这就要求对Netfilter连接跟踪模块要比较熟悉,才能做好二次开发。本文主要解析了Netfilter连接跟踪状态,更准确的说是skb数据包的连接状态。 </p> <p> 本文是基于Linux 3.3.8内核代码进行解析的。 </p> <h2> 连接跟踪状态 </h2> <p> 下面代码是Netfilter定义的各种连接状态: </p> <pre><code>enum ip_conntrack_info { /* Part of an established connection (either direction). */ IP_CT_ESTABLISHED, /* Like NEW, but related to an existing connection, or ICMP error (in either direction). */ IP_CT_RELATED, /* Started a new connection to track (only IP_CT_DIR_ORIGINAL); may be a retransmission. */ IP_CT_NEW, /* &gt;= this indicates reply direction */ IP_CT_IS_REPLY, IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY, IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY, IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY, /* Number of distinct IP_CT types (no NEW in reply dirn). */ IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 }; </code></pre> <p> 接下来将对每一种具体状态进行解析。 </p> <h3> <code>IP_CT_ESTABLISHED</code> </h3> <p> 毫无疑问,表示连接建立。请注意不要与TCP连接搞混,这里的连接是广义的连接。 什么时候内核判定为连接已经建立了呢?在连接匹配函数<code>resolve_normal_ct</code>中: </p> <pre><code>/* It exists; we have (non-exclusive) reference. */ if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) { *ctinfo = IP_CT_ESTABLISHED_REPLY; *set_reply = 1; } else { /* Once we've had two way comms, always ESTABLISHED. */ if (test_bit(IPS_SEEN_REPLY_BIT, &amp;ct-&gt;status)) { pr_debug("nf_conntrack_in: normal packet for %p\n", ct); *ctinfo = IP_CT_ESTABLISHED; } ...... ...... } </code></pre> <p> 从上面的代码中,可以看成,在内核收到ORIGINAL方向的数据包,并且设置了<code>IPS_SEEN_REPLY_BIT</code>(看到过REPLY方向的数据包)时,就将连接状态设置为<code>IP_CT_ESTABLISHED</code>。也就是说,在内核收到双方向数据包后,并再次收到ORIGINAL方向数据包时,即视连接已经建立。 </p> <p> 那么<code>IPS_SEEN_REPLY_BIT</code>什么时候被设置上的呢?上面的代码中可以看到*set_reply被设置为1。在<code>nf_conntrack_in</code>中, </p> <pre><code> if (set_reply &amp;&amp; !test_and_set_bit(IPS_SEEN_REPLY_BIT, &amp;ct-&gt;status)) nf_conntrack_event_cache(IPCT_REPLY, ct); </code></pre> <p> 如果发现set_reply被赋值为1,则设置<code>IPS_SEEN_REPLY_BIT</code>标志位。 </p> <h3> <code>IP_CT_RELATED</code> </h3> <p> 表示一个与其它连接关联的新建连接。<br /> 1)在<code>icmp_error_message</code>中,如果收到的是ICMP报文,并且根据其payload找到了已有连接,则将连接状态设置为<code>IP_CT_RELATED</code>。<br /> 2)在<code>init_conntrack</code>中新建连接时,发现其匹配一个expect连接,则将其设置上<code>IPS_EXPECTED_BIT</code>标志。在<code>resolve_normal_ct</code>中发现数据包是ORIGINAL方向并且没有收到过REPLY方向的数据包,并且连接设置了<code>IPS_EXPECTED_BIT</code>标志,则该数据包的连接状态则设置为<code>IP_CT_RELATED</code>。 </p> <pre><code> if (test_bit(IPS_SEEN_REPLY_BIT, &amp;ct-&gt;status)) { ...... ...... } else if (test_bit(IPS_EXPECTED_BIT, &amp;ct-&gt;status)) { pr_debug("nf_conntrack_in: related packet for %p\n", ct); *ctinfo = IP_CT_RELATED; } else { pr_debug("nf_conntrack_in: new packet for %p\n", ct); *ctinfo = IP_CT_NEW; } </code></pre> <h3> <code>IP_CT_NEW</code> </h3> <p> 表示一个新建连接. 与<code>IP_CT_RELATED</code>相似,只不过在新建连接时没有匹配中expect连接,从而没有设置上EXPECTED标志。这样当收到ORIGINAL方向的数据包,并且没有收到过REPLY方向数据包,连接又没有EXPECTED标志,则数据包的连接状态为<code>IP_CT_NEW</code>。 </p> <h3> <code>IP_CT_IS_REPLY</code> </h3> <p> 这并不是一个单一状态,更像一个标志位作用。目前只有在<code>icmp_error_message</code>中使用: </p> <pre><code>if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) *ctinfo += IP_CT_IS_REPLY; </code></pre> <p> 当发现关联的tuple是REPLY方向,则给数据包的连接状态设置上<code>IP_CT_IS_REPLY</code>状态。 </p> <h3> <code>IP_CT_ESTABLISHED_REPLY</code> </h3> <p> 在<code>resolve_normal_ct</code>中,只要收到REPLY方向的数据包就设置为<code>IP_CT_ESTABLISHED_REPLY</code>。 </p> <h3> <code>IP_CT_NEW_REPLY</code> </h3> <p> 从字面上看是一个REPLY方向的新建连接状态。本身这就是一个矛盾,或者说不可能存在的状态。对于Netfilter来说,发起连接的方向,被认为是ORIGINAL方向。那么就不可能存在REPLY方向上的新建连接。目前在内核代码中也没有使用这个状态。 </p>
阅读(9840) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册