免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2692 | 回复: 7

关于Netfilter中连接跟踪机制的方向问题 Original or Relay [复制链接]

论坛徽章:
0
发表于 2010-10-26 20:57 |显示全部楼层
内核版本2.6.30
由于之前一直在2.4版本的内核,现在刚刚改用2.6.30,其内核一些数据结构和实现机制都发送了改变,因此变写了几个小程序去验证性的跑一下,结果却发现了这个另我费解的问题。。。
本意是在测试最新版本内核中连接跟踪模块的使用情况,在新版本内核中通过struct nf_conn代替之前的ip_conntrack结构,但其中主要的一个数据结构
struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]并没有太大改变。
好了,问题来了,按照道理说这个连接数组中        IP_CT_DIR_ORIGINAL代表的应该是原始方向的数据包,其源地址应该与ip头部中的源地址是相同的,而IP_CT_DIR_REPLY代表回复方向的数据包,其目的地址才应该为本机地址。(这是我之前的理解)
但是在我写的一个小测试用例中,得到的结果恰恰相反,ORIGINAL方向的连接的目的地址才是ip头部中的源地址,RELAY方向连接的源地址才是ip头部中的目的地址,很是困惑,想不明白,难道说是我之前对于连接跟踪方向一直理解错了吗?。。。
现在贴一下我的代码以及测试结果,有些长,各位看官不要嫌麻烦,因此这个问题真的很困扰我,急求给为牛人解惑,小弟不胜感激。。。。
  1. #include  <linux/module.h>
  2. #include  <linux/init.h>
  3. #include  <linux/kernel.h>

  4. #include  <linux/types.h>
  5. #include  <linux/errno.h>
  6. #include  <linux/sched.h>
  7. #include  <linux/slab.h>
  8. #include  <linux/fs.h>
  9. #include  <linux/poll.h>
  10. #include  <linux/spinlock.h>
  11. #include        <linux/ioctl.h>
  12. #include        <linux/proc_fs.h>
  13. #include        <linux/list.h>
  14. #include        <linux/param.h>
  15. #include        <asm/uaccess.h>
  16. #include        <asm/atomic.h>


  17. #include        <linux/skbuff.h>
  18. #include        <linux/in.h>
  19. #include        <linux/ip.h>
  20. #include        <linux/tcp.h>
  21. #include        <linux/udp.h>
  22. #include        <linux/icmp.h>
  23. #include        <linux/netdevice.h>
  24. #include        <linux/netfilter.h>
  25. #include        <linux/netfilter_ipv4.h>
  26. #include <linux/netfilter/nf_conntrack_tuple_common.h>
  27. #include <net/netfilter/nf_conntrack.h>

  28. #include        <linux/byteorder/generic.h>
  29. #include        <linux/if_arp.h>
  30. #include        <linux/if_ether.h>
  31. #include        <linux/if_packet.h>
  32. #include        <linux/delay.h>

  33. #define HASH_SIZE 1024

  34. static unsigned int       
  35. conn_hook(unsigned int hook,
  36.                            struct sk_buff *skb,
  37.                            const struct net_device *indev,
  38.                            const struct net_device *outdev,
  39.                            int        (*okfn)(struct sk_buff *))
  40. {
  41.         struct nf_conn *conn;
  42.         struct nf_conntrack_tuple_hash tuple_list;
  43.         struct nf_conntrack_tuple orig_tuple;
  44.         struct nf_conntrack_tuple relay_tuple;
  45.         struct iphdr *iph;
  46.         struct tcphdr *tcph;
  47.         u32 ip_saddr;
  48.         u32 ip_daddr;
  49.        
  50.         if(!skb)
  51.                 {
  52.                         return NF_ACCEPT;       
  53.                 }
  54.         printk("Hook functions\n");
  55.         //获取连接跟踪数据结构
  56.         conn = (struct nf_conn *)(skb->nfct);
  57.         if(!conn)
  58.                 {
  59.                         printk("no nf_conntrack \n");
  60.                         return NF_ACCEPT;       
  61.                 }
  62.                
  63. #if 1
  64.         iph = ip_hdr(skb);
  65.         tcph = tcp_hdr(skb);
  66.         printk("ipv4 src addr: %d.%d.%d.%d,dst addr:%d.%d.%d.%d\n", NIPQUAD(iph->saddr),NIPQUAD(iph->daddr));
  67.         printk("ipv4 tcp src port %d, dst port %d\n",tcph->source,tcph->dest);
  68.         tuple_list = conn->tuplehash[IP_CT_DIR_REPLY];
  69.         orig_tuple = conn->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
  70.         relay_tuple = conn->tuplehash[IP_CT_DIR_REPLY].tuple;
  71.         ip_saddr = orig_tuple.src.u3.ip;
  72.         ip_daddr = orig_tuple.dst.u3.ip;
  73.         printk("ipv4 original src addr: %d.%d.%d.%d,dst src addr: %d.%d.%d.%d\n", NIPQUAD(ip_saddr),NIPQUAD(ip_daddr));
  74.         printk("src original port: %d,dst prot: %d\n",orig_tuple.src.u.tcp.port,orig_tuple.dst.u.tcp.port);       
  75.         ip_saddr = relay_tuple.src.u3.ip;
  76.         ip_daddr = relay_tuple.dst.u3.ip;
  77.         printk("ipv4 relay src addr: %d.%d.%d.%d,dst src addr: %d.%d.%d.%d\n", NIPQUAD(ip_saddr),NIPQUAD(ip_daddr));
  78.         printk("src relay port: %d,dst prot: %d\n",relay_tuple.src.u.tcp.port,relay_tuple.dst.u.tcp.port);
  79. #endif

  80.         return NF_ACCEPT;
  81. }

  82. static struct nf_hook_ops conn_hook_ops = {
  83. .hook =       conn_hook,
  84. .pf =         PF_INET,
  85. .hooknum =    NF_INET_POST_ROUTING,
  86. .priority =    NF_IP_PRI_LAST-1,
  87. };

  88. static int conn_init(void)
  89. {
  90.         int ret = 0;
  91. //注册钩子
  92.         ret = nf_register_hook(&conn_hook_ops);
  93.         if (ret < 0)
  94.         {
  95.                 printk("register isatap hook ops error!\n");
  96.         return -ENOMEM;
  97.         }
  98.     return 0;
  99. }

  100. static void conn_exit(void)
  101. {
  102.         nf_unregister_hook(&conn_hook_ops);       
  103.         printk("Unregister conntrack hook ok\n");
  104.         return;
  105. }

  106. module_init(conn_init);
  107. module_exit(conn_exit);

  108. MODULE_LICENSE("GPL");
复制代码
然后使运行结果;
  1. Hook functions
  2. ipv4 src addr: 192.168.1.4,dst addr:192.168.1.221
  3. ipv4 tcp src port 5632, dst port 2824
  4. ipv4 original src addr: 192.168.1.221,dst src addr: 192.168.1.4
  5. src original port: 2824,dst prot: 5632
  6. ipv4 relay src addr: 192.168.1.4,dst src addr: 192.168.1.221
  7. src relay port: 5632,dst prot: 2824
  8. Hook functions
  9. ipv4 src addr: 192.168.1.4,dst addr:192.168.1.221
  10. ipv4 tcp src port 5632, dst port 2824
  11. ipv4 original src addr: 192.168.1.221,dst src addr: 192.168.1.4
  12. src original port: 2824,dst prot: 5632
  13. ipv4 relay src addr: 192.168.1.4,dst src addr: 192.168.1.221
  14. src relay port: 5632,dst prot: 2824
  15. Hook functions
  16. ipv4 src addr: 192.168.1.4,dst addr:192.168.1.221
  17. ipv4 tcp src port 5632, dst port 2824
  18. ipv4 original src addr: 192.168.1.221,dst src addr: 192.168.1.4
  19. src original port: 2824,dst prot: 5632
  20. ipv4 relay src addr: 192.168.1.4,dst src addr: 192.168.1.221
  21. src relay port: 5632,dst prot: 2824
  22. Hook functions
  23. ipv4 src addr: 192.168.1.4,dst addr:192.168.1.221
  24. ipv4 tcp src port 5632, dst port 10760
  25. ipv4 original src addr: 192.168.1.221,dst src addr: 192.168.1.4
  26. src original port: 10760,dst prot: 5632
  27. ipv4 relay src addr: 192.168.1.4,dst src addr: 192.168.1.221
  28. src relay port: 5632,dst prot: 10760
复制代码
从这个结果来看,ip首部的源地址和目的地址对应的是relay方向的连接包,通过tcp头部的端口号也证明了这一点。。。
而且我刚刚看了下ipv4_pkt_to_tuple,它所做的工作的确是从ip首部自动的源地址开始,读取两个32字节的变量,分别赋给tuple中的源地址和目的地址,按照道理说应该不会出错啊,可是我怎么得出了这么个结果。。。

这个真的很困惑,本人也是刚开始学Netfilter不久,还请各位高手帮忙解答。。。

论坛徽章:
0
发表于 2010-10-26 20:59 |显示全部楼层
貌似我忘记考虑端口的网络字节序的问题了。。。。
各位请直接跳过这个问题

论坛徽章:
0
发表于 2010-10-26 21:03 |显示全部楼层
操作系统Centos,实验平台虚拟机,应该没有需要补充的了。。。

论坛徽章:
0
发表于 2010-10-27 09:09 |显示全部楼层
没人能帮忙看一下吗。。。
哎。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2010-10-27 10:11 |显示全部楼层
# static struct nf_hook_ops conn_hook_ops = {
# .hook =       conn_hook,
# .pf =         PF_INET,
# .hooknum =    NF_INET_POST_ROUTING,
# .priority =    NF_IP_PRI_LAST-1,
# };


本身数据包又流入和流出两个方向,都会通过连接跟踪的。
你看一下你的 hook 函数注册的位置,如果是终端主机的话,只有哪个方向的包才会进入你的 hook 函数

论坛徽章:
0
发表于 2010-10-27 10:29 |显示全部楼层
回复 5# Godbach


    注册点在 POST_ROUTING,测试机是终端主机,按照道理在LOCAL_OUT的时候会对本机发出的数据包建立连接跟踪,在POST_ROUTING中挂入连接跟踪队列中

    目的是为了测试本机发出的数据包,在POST_ROUTING也不能捕获到达本机的数据包吧,测试中那个192.168.1.4是运行程序的主机ip地址,192.168.1.221为发出数据包的目的地址

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2010-10-27 10:54 |显示全部楼层
首先要明确你这个连接主动发起方是哪个 IP。
可以做个测试,用另一台主机向你当前主机发起 SYN 请求,或者等连接完全建立之后也行,你在 LOCALIN 出截获它的数据包,并查看连接的 ORG 方向的源 IP.

论坛徽章:
0
发表于 2010-10-27 22:50 |显示全部楼层
本帖最后由 奇门遁甲-lu 于 2010-10-27 23:11 编辑

很明显你的数据是由
192.168.1.221开始发出的。
数据通过连接跟踪,如果还没建立连接跟踪的,就建立一个连接跟踪
你的挂钩放在NF_INET_POST_ROUTING。

实际上是192.168.1.4应答的时候捕捉到的数据。

所以
ipv4 original src addr: 192.168.1.221,dst src addr: 192.168.1.4
一点没错,
IP_CT_DIR_ORIGINAL记录的是数据最开始时的方向,

另外应该判断一下传输协层议协议是不是tcp.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP