登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

ideality

@linux c 编程@

 
 
 

日志

 
 
 
 

教你修改以及重构skb(转)  

2012-12-25 21:32:23|  分类: netfilter |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
测试环境:
   CentOS5.3 2.6.18
工具:
   sendip和wireshark
   sendip可以发送各种数据包,确实方便.wireshark图形化的显示对于分析整个数据包还是相当不错的...
   
一:内核态基于Netfilter构造数据包
主要有两种方式:
1. alloc_skb申请一个skb结构体,然后根据实际的应用填充不同的成员,或者基于当前数据包的skb,
   调用skb_copy() pskb_copy() skb_copy_expand()等新申请一个nskb,并且拷贝skb的内容。
2. 直接在先前接收到的数据包skb上作修改,主要有源IP、目IP,如果是TCP/UDP协议的话,还有源端口目的端口号。
  就是根据你自己的需求去调整数据包的相关成员即可。然后重新计算各个部分的校验和。

   不管你第一种方式还是第二种方式,你需要知道你也必须知道的就是对于l2 l3 l4层的数据你都必须去构造,我之前就是
由于没有构造L2而郁闷了一天...
   让我们先从一个小程序开始,把5个hook都挂上mac这个函数,主要就是看看l2,对于l3 l4以及应用层我以前的几个帖子里面
已经有很多了,这里就不说了      
  1.    printk("------begin %s--------\n", hooks[hooknum]);
  2.    print_ipproto(iph->protocol);
  3.    printk("len is %d, data len is %d\n", nskb->len, nskb->data_len);
  4.    if(nskb->mac_len > 0)
  5.            {
  6.             eth = (struct ethhdr*)(nskb->mac.raw);
  7.             print_mac(eth);        
  8.                    }    
  9.    printk("------end  %s--------\n", hooks[hooknum]);
复制代码

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/netfilter.h>
  5. #include <linux/skbuff.h>
  6. #include <linux/ip.h>
  7. #include <linux/netdevice.h>
  8. #include <linux/if_ether.h>
  9. #include <linux/if_packet.h>
  10. #include <net/tcp.h>
  11. #include <net/udp.h>
  12. #include <net/icmp.h>
  13. #include <linux/netfilter_ipv4.h>

  14. #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
  15. #define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]

  16. MODULE_LICENSE("GPL");
  17. MODULE_AUTHOR("kenthy@163.com");

  18. const char* hooks[] ={ "NF_IP_PRE_ROUTING",
  19.                              "NF_IP_LOCAL_IN",
  20.                              "NF_IP_FORWARD",
  21.                              "NF_IP_LOCAL_OUT",
  22.                              "NF_IP_POST_ROUTING"};

  23. void print_ipproto(int proto)
  24. {
  25. switch(proto)
  26. {
  27.         case IPPROTO_ICMP:
  28.                 printk("%s\n", "IPPROTO_ICMP");
  29.           break;
  30.         case IPPROTO_TCP:
  31.                 printk("%s\n", "IPPROTO_TCP");
  32.           break;
  33.         case IPPROTO_UDP:
  34.                 printk("%s\n", "IPPROTO_UDP");
  35.           break;
  36.         default:
  37.                 printk("%s\n", "other IPPROTO");
  38.         }
  39. }

  40. void print_mac(struct ethhdr* eth)
  41. {
  42. if(eth==NULL)
  43.         return;
  44.         
  45. if(eth->h_source!=NULL)
  46.         printk("SOURCE:" MAC_FMT "\n", MAC_ARG(eth->h_source));

  47. if(eth->h_dest!=NULL)
  48.              printk("DEST:" MAC_FMT "\n", MAC_ARG(eth->h_dest));
  49. }

  50. unsigned int
  51. mac(unsigned int hooknum,
  52.                  struct sk_buff** skb,
  53.                  const struct net_device *in,
  54.                  const struct net_device *out,
  55.                  int (*okfn)(struct sk_buff*))
  56. {
  57.    struct sk_buff* nskb;
  58.    struct iphdr *iph = NULL;
  59.    struct ethhdr* eth;
  60.   
  61.   nskb = *skb;
  62.   if(nskb==NULL)
  63.   {
  64.     printk("%s\n", "*skb is NULL");
  65.     return NF_ACCEPT;
  66.    }
  67.   
  68.   iph = ip_hdr(nskb);
  69.   if(iph == NULL)
  70.   {
  71.     printk("%s\n", "*iph is NULL");
  72.     return NF_ACCEPT;
  73.    }

  74.       
  75.    printk("------begin %s--------\n", hooks[hooknum]);
  76.    print_ipproto(iph->protocol);
  77.    printk("len is %d, data len is %d\n", nskb->len, nskb->data_len);
  78.    if(nskb->mac_len > 0)
  79.            {
  80.             eth = (struct ethhdr*)(nskb->mac.raw);
  81.             print_mac(eth);        
  82.                    }
  83.    else
  84.     printk("%s", "mac is NULL");                
  85.     
  86.     
  87.    printk("------end  %s--------\n", hooks[hooknum]);
  88.   
  89.     return NF_ACCEPT;
  90. }

  91.                              
  92. static struct nf_hook_ops mac_ops[] = {
  93.         {
  94.                 .hook                = mac,
  95.                 .owner                = THIS_MODULE,
  96.                 .pf                = PF_INET,
  97.                 .hooknum        = NF_IP_PRE_ROUTING,
  98.                 .priority = NF_IP_PRI_FIRST,
  99.         },
  100.         {
  101.                 .hook                = mac,
  102.                 .owner                = THIS_MODULE,
  103.                 .pf                = PF_INET,
  104.                 .hooknum        = NF_IP_LOCAL_IN,
  105.                 .priority = NF_IP_PRI_FIRST,
  106.         },
  107.         {
  108.                 .hook                = mac,
  109.                 .owner                = THIS_MODULE,
  110.                 .pf                = PF_INET,
  111.                 .hooknum        = NF_IP_FORWARD,
  112.                 .priority = NF_IP_PRI_FIRST,
  113.         },
  114.         {
  115.                 .hook                = mac,
  116.                 .owner                = THIS_MODULE,
  117.                 .pf                = PF_INET,
  118.                 .hooknum        = NF_IP_LOCAL_OUT,
  119.                 .priority = NF_IP_PRI_FIRST,
  120.         },
  121.         {
  122.                 .hook                = mac,
  123.                 .owner                = THIS_MODULE,
  124.                 .pf                = PF_INET,
  125.                 .hooknum        = NF_IP_PRE_ROUTING,
  126.                 .priority = NF_IP_POST_ROUTING,
  127.         },
  128. };

  129. static int __init init(void)
  130. {
  131.     int ret;
  132.     ret = nf_register_hooks(mac_ops, ARRAY_SIZE(mac_ops));
  133.     if (ret < 0) {
  134.         printk("http detect:can't register mac_ops detect hook!\n");
  135.         return ret;
  136.     }
  137.     printk("insmod mac_ops detect module\n");
  138.     return 0;
  139. }

  140. static void __exit fini(void)
  141. {
  142.     nf_unregister_hooks(mac_ops, ARRAY_SIZE(mac_ops));
  143.     printk("remove mac_ops detect module.\n");
  144. }

  145. module_init(init);
  146. module_exit(fini);
复制代码

  insmod mac.ko加载mac模块后,随便发个ping包
  Jan 10 09:44:13 nfs-client kernel: ------begin NF_IP_LOCAL_OUT--------
Jan 10 09:44:13 nfs-client kernel: IPPROTO_ICMP
Jan 10 09:44:13 nfs-client kernel: len is 84, data len is 0
Jan 10 09:44:13 nfs-client kernel: mac is NULL------end  NF_IP_LOCAL_OUT--------
Jan 10 09:44:13 nfs-client kernel: ------begin NF_IP_PRE_ROUTING--------
Jan 10 09:44:13 nfs-client kernel: IPPROTO_ICMP
Jan 10 09:44:13 nfs-client kernel: len is 84, data len is 0
Jan 10 09:44:13 nfs-client kernel: SOURCE:00:50:56:fa:70:2a
Jan 10 09:44:13 nfs-client kernel: DEST:00:0c:29:4f:de:ac
Jan 10 09:44:13 nfs-client kernel: ------end  NF_IP_PRE_ROUTING--------
Jan 10 09:44:13 nfs-client kernel: ------begin NF_IP_LOCAL_IN--------
Jan 10 09:44:13 nfs-client kernel: IPPROTO_ICMP
Jan 10 09:44:13 nfs-client kernel: len is 84, data len is 0
Jan 10 09:44:13 nfs-client kernel: SOURCE:00:50:56:fa:70:2a
Jan 10 09:44:13 nfs-client kernel: DEST:00:0c:29:4f:de:ac
Jan 10 09:44:13 nfs-client kernel: ------end  NF_IP_LOCAL_IN--------
   可以看到对于挂载在out上的数据包mac已经被剥掉

当接收一个包时,处理n层协议头的函数从n-1层收到一个缓冲区,它的skb->data指向n层协议的头。处理n层协议的函数把本层的指针(例如,L3对应的是skb->nh指针)初始化为skb->data,因为这个指针的值会在处理下一层协议时改变(skb->data将被初始化成缓冲区里的其他地址)。在处理n层协议的函数结束时,在把包传递给n+1层的处理函数前,它会把skb->data指针指向n层协议头的末尾,这正好是n+1层协议的协议头。 

发送包的过程与此相反,但是由于要为每一层添加新的协议头,这个过程要比接收包的过程复杂。 
  评论这张
 
阅读(626)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018