linux 内核开发-重构skb

测试环境:
   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。

 

 

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层协议的协议头。 

发送包的过程与此相反,但是由于要为每一层添加新的协议头,这个过程要比接收包的过程复杂。

sk_buff_003.jpg

好的,到现在你已经知道要重新搞一个数据包需要自己来DIY l2 l3 l4当然还有l7如果你想....   
    来先看看skb的几个重要指针吧
unsigned char *head
unsigned char *end
unsigned char *data
unsigned char *tail
它们表示缓冲区和数据部分的边界。在每一层申请缓冲区时,它会分配比协议头或协议数据大的空间。head和end指向缓冲区的头部和尾部,而data和tail指向实际数据的头部和尾部。每一层会在head和data之间填充协议头,或者在tail和end之间添加新的协议数据 

sk_buff_002.jpg 

那么具体操作这些指针呢?
(a)skb_put, (b)skb_push, (c)skb_pull, and (d)skb_reserve

sk_buff_004.jpg 

再加上dev_queue_xmit这个函数,你已经可以完成整件事了,对你现在有点蒙感觉无从下手,我也是!!! 我是历经几十次的死机才成功的,写这个文章也是希望后来人少走点弯路...

  那就从修改开始吧....

 

测试结果:

sendip -p ipv4 -is 192.168.238.180 -p tcp -ts 598982 -td 80 192.168.1.1 
//                                  sip                                 sport       dport  dip
sendip比较好用吧,你可以指定syn ack之类的呢

skb_modify.JPG 

上面的三个数据包是没有加载skb_modify模块的...上面的具体函数你们可以sourceinsight跟踪看看,我也不可能一一讲解  

因为我们是挂在NF_IP_LOCAL_OUT上所以我们需要重新搞mac header

那么DIY SKB呢?

 

测试结果:

skb_diy.JPG 

我这里并没有填充上层的东西 但是已经提供接口 
pdata = skb_put (skb, pkt_len); 
  {
    if (NULL != pkt) 
     memcpy (pdata, pkt, pkt_len);
  }

你可以自己先截获一个上层的包再填充进去...  关于上层的东西我开源应用层DPI--l7detect初步成果 已经很清楚了,都已经DPI了  

 

 

来源:http://bbs.chinaunix.net/thread-1941060-1-1.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值