免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 59610 | 回复: 68
打印 上一主题 下一主题

[网络子系统] linux-2.6.35.6 nf_conntrack [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-05-21 21:07 |只看该作者 |正序浏览
本帖最后由 pywj777 于 2013-05-22 01:03 编辑

最近在整理以前的笔记,在Godbach的鼓励下,准备写一个有关nf_conntrack的总结。与之前写的iptables算是姐妹篇,因为iptables和nf_conntrack应该算是netfilter中比较重要的两个模块了。同时它们之间也互相搭配应用。还是老样子,多上图,少上字。

我认为理解一个程序的实现主要从两点来理解,一个是业务的处理流程,另一个就是数据的组织结构。根据这两点,我们先来介绍几个重要的数据结构:

连接跟踪,顾名思义,就是识别一个连接上双方向的数据包,同时记录状态。下面看一下它的数据结构:
struct nf_conn {
        /* Usage count in here is 1 for hash table/destruct timer, 1 per skb, plus 1 for any connection(s) we are `master' for */
        struct  nf_conntrack  ct_general;                /* 连接跟踪的引用计数 */
        spinlock_t  lock;

        /* Connection tracking(链接跟踪)用来跟踪、记录每个链接的信息(目前仅支持IP协议的连接跟踪)。
            每个链接由“tuple”来唯一标识,这里的“tuple”对不同的协议会有不同的含义,例如对tcp,udp
                 来说就是五元组: (源IP,源端口,目的IP, 目的端口,协议号),对ICMP协议来说是: (源IP, 目
            的IP, id, type, code), 其中id,type与code都是icmp协议的信息。链接跟踪是防火墙实现状态检
            测的基础,很多功能都需要借助链接跟踪才能实现,例如NAT、快速转发、等等。*/

        struct  nf_conntrack_tuple_hash  tuplehash[IP_CT_DIR_MAX];
       
        unsigned long  status;                             /* 可以设置由enum ip_conntrack_status中描述的状态 */

        struct  nf_conn  *master;                        /* 如果该连接是某个连接的子连接,则master指向它的主连接 */
        /* Timer function; drops refcnt when it goes off. */
        struct  timer_list  timeout;

        union nf_conntrack_proto proto;                /* 用于保存不同协议的私有数据 */
        /* Extensions */
        struct nf_ct_ext *ext;                        /* 用于扩展结构 */
};
这个结构非常简单,其中最主要的就是tuplehash(跟踪连接双方向数据)和status(记录连接状态),这也连接跟踪最主要的功能。

在status中可以设置的标志,由下面的enum ip_conntrack_status描述,它们可以共存。这些标志设置后就不会再被清除。
enum ip_conntrack_status {
        IPS_EXPECTED_BIT = 0,                /* 表示该连接是个子连接 */
        IPS_SEEN_REPLY_BIT = 1,                /* 表示该连接上双方向上都有数据包了 */
        IPS_ASSURED_BIT = 2,                /* TCP:在三次握手建立完连接后即设定该标志。UDP:如果在该连接上的两个方向都有数据包通过,
                                                                则再有数据包在该连接上通过时,就设定该标志。ICMP:不设置该标志 */

        IPS_CONFIRMED_BIT = 3,                /* 表示该连接已被添加到net->ct.hash表中 */
        IPS_SRC_NAT_BIT = 4,                /*在POSTROUTING处,当替换reply tuple完成时, 设置该标记 */
        IPS_DST_NAT_BIT = 5,                /* 在PREROUTING处,当替换reply tuple完成时, 设置该标记 */
        /* Both together. */
        IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),
        /* Connection needs TCP sequence adjusted. */
        IPS_SEQ_ADJUST_BIT = 6,
        IPS_SRC_NAT_DONE_BIT = 7,        /* 在POSTROUTING处,已被SNAT处理,并被加入到bysource链中,设置该标记 */
        IPS_DST_NAT_DONE_BIT = 8,        /* 在PREROUTING处,已被DNAT处理,并被加入到bysource链中,设置该标记 */
        /* Both together */
        IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
        IPS_DYING_BIT = 9,                /* 表示该连接正在被释放,内核通过该标志保证正在被释放的ct不会被其它地方再次引用。有了这个标志,当某个连接要被删
                                                          除时,即使它还在net->ct.hash中,也不会再次被引用。*/

        IPS_FIXED_TIMEOUT_BIT = 10,        /* 固定连接超时时间,这将不根据状态修改连接超时时间。通过函数nf_ct_refresh_acct()修改超时时间时检查该标志。 */
        IPS_TEMPLATE_BIT = 11,                /* 由CT target进行设置(这个target只能用在raw表中,用于为数据包构建指定ct,并打上该标志),用于表明这个ct是由CT target创建的 */
};

连接跟踪对该连接上的每个数据包表现为以下几种状态之一,由enum ip_conntrack_info表示,被设置在skb->nfctinfo中。
enum ip_conntrack_info {
IP_CT_ESTABLISHED(0),         /* 表示这个数据包对应的连接在两个方向都有数据包通过,并且这是ORIGINAL初始方向数据包(无论是TCP、UDP、ICMP数据包,
                                                      只要在该连接的两个方向上已有数据包通过,就会将该连接设置为IP_CT_ESTABLISHED状态。不会根据协议中的标志位进行判断,
                                                      例如TCP的SYN等)。但它表示不了这是第几个数据包,也说明不了这个CT是否是子连接。*/

IP_CT_RELATED(1),                /* 表示这个数据包对应的连接还没有REPLY方向数据包,当前数据包是ORIGINAL方向数据包。并且这个连接关联一个已有的连接,
                                                      是该已有连接的子连接,(即status标志中已经设置了IPS_EXPECTED标志,该标志在init_conntrack()函数中设置)。但无法
                                                      判断是第几个数据包(不一定是第一个)*/

IP_CT_NEW(2),                        /* 表示这个数据包对应的连接还没有REPLY方向数据包,当前数据包是ORIGINAL方向数据包,该连接不是子连接。但无法判断是
                                                      第几个数据包(不一定是第一个)*/

IP_CT_IS_REPLY(3),                /* 这个状态一般不单独使用,通常以下面两种方式使用 */
IP_CT_ESTABLISHED + IP_CT_IS_REPLY(3),        /* 表示这个数据包对应的连接在两个方向都有数据包通过,并且这是REPLY应答方向数据包。但它表示不了这是
                                                                               第几个数据包,也说明不了这个CT是否是子连接。*/

IP_CT_RELATED + IP_CT_IS_REPLY(4),                /* 这个状态仅在nf_conntrack_attach()函数中设置,用于本机返回REJECT,例如返回一个ICMP目的不可达报文,
                                                                               或返回一个reset报文。它表示不了这是第几个数据包。*/

IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1(5)        /* 可表示状态的总数 */
};

以上就是连接跟踪里最重要的数据结构了,用于跟踪连接、记录状态、并对该连接的每个数据包设置一种状态。

评分

参与人数 3可用积分 +32 收起 理由
embeddedlwp + 10 赞一个!
send_linux + 12 感谢原创分享
Godbach + 10 很给力!

查看全部评分

论坛徽章:
0
69 [报告]
发表于 2015-01-15 22:26 |只看该作者
回复 17# Godbach

斑竹,帮忙解答下这个问题http://bbs.chinaunix.net/thread-4166580-1-1.html
   

论坛徽章:
0
68 [报告]
发表于 2015-01-15 22:23 |只看该作者
回复 64# pywj777


  大神帮忙看看这个问题http://bbs.chinaunix.net/thread-4166580-1-1.html

论坛徽章:
0
67 [报告]
发表于 2014-12-03 23:47 |只看该作者
楼主 我还一个新问题关于带选项分片报文转发的问题,发了个问题贴,帮忙解决下吧,
http://bbs.chinaunix.net/forum.p ... =4162731&extra=

论坛徽章:
0
66 [报告]
发表于 2014-10-24 00:52 |只看该作者
2

论坛徽章:
8
羊年新春福章
日期:2015-03-19 02:03:312015亚冠之北京国安
日期:2015-06-16 22:04:45程序设计版块每日发帖之星
日期:2015-06-23 22:20:00每日论坛发贴之星
日期:2015-06-23 22:20:002015亚冠之首尔
日期:2015-06-24 19:18:072015亚冠之广州恒大
日期:2015-08-06 10:29:442015亚冠之柏太阳神
日期:2015-11-02 11:21:0515-16赛季CBA联赛之辽宁
日期:2015-12-09 15:05:02
65 [报告]
发表于 2014-10-13 15:15 |只看该作者
感谢, lz解答, 明白了.
回复 64# pywj777


   

论坛徽章:
0
64 [报告]
发表于 2014-10-13 12:25 |只看该作者
本帖最后由 pywj777 于 2014-10-13 12:27 编辑

回复 62# firocu

第8条上有个关键点,就是:数据包永远都是在PREROUTING链做目的地址和目的端口转换,在POSTROUTING链做原地址和原端口转换。
你问的问题是在POSTROUTING点上做了SNAT,那么回来报文则要做相应的DNAT,也就是要在PREROUTING点上做,回来的报文在POSTROUTING点上不需做任何事情。
在PREROUTING点上要做的事情描述如下:
在PREROUTING链上--->数据包是original方向、并且连接上设置IPS_DST_NAT标志,或数据包是reply方向、并且连接上设置IPS_SRC_NAT标志,则做DNAT转换。

   

论坛徽章:
0
63 [报告]
发表于 2014-10-13 12:17 |只看该作者
本帖最后由 pywj777 于 2014-10-13 12:19 编辑

回复 60# lunixwh

没错,你观察的很细致,这里确实多了个sizeof(struct nf_ct_ext)。并且在linux-3.15.1中已经将它改正过来了。
代码改为: t1->alloc_size = ALIGN(sizeof(struct nf_ct_ext), t1->align) + t1->len;

   

论坛徽章:
8
羊年新春福章
日期:2015-03-19 02:03:312015亚冠之北京国安
日期:2015-06-16 22:04:45程序设计版块每日发帖之星
日期:2015-06-23 22:20:00每日论坛发贴之星
日期:2015-06-23 22:20:002015亚冠之首尔
日期:2015-06-24 19:18:072015亚冠之广州恒大
日期:2015-08-06 10:29:442015亚冠之柏太阳神
日期:2015-11-02 11:21:0515-16赛季CBA联赛之辽宁
日期:2015-12-09 15:05:02
62 [报告]
发表于 2014-10-12 00:28 |只看该作者
感谢lz辛劳分享.
请教一个问题.
对与第八条
在POSTROUTING链上--->数据包是original方向、并且连接上设置IPS_SRC_NAT标志,或数据包是reply方向、并且连接上设置IPS_DST_NAT标志,则做SNAT转换。

比如我再POSTROUTING上做了各SNAT, 那么回来的报文对应的ct->status的IPS_DST_NAT这个标志位是什么时候被打上的呢?

论坛徽章:
0
61 [报告]
发表于 2014-09-23 17:26 |只看该作者
回复 60# lunixwh


    可能是做管理用,熟悉的请解答。
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP