根据五元组对pcap数据包划分

目的

对数据包(pacp格式)中的数据,按照五元组(#流:源端口号、目的端口号、协议号、源IP、目的IP)对流进行划分。

举例:flow1(data[IP].src, data.sport, data[IP].dst, data.dport, data.proto)。

思路

五元组提取

首先对每个数据包进行遍历,提取出里面有效的五元组信息。

在实践中:

  • 因为抓包在链路层,可能有些包是ARP协议等,所以没有上层信息,视为无效包。
  • 还有些数据包缺失端口号或者协议(无tcp,udp等扽标识),暂时没思考出来为什么,会抛出异常,视为无效包。所以在代码中需要加入异常处理。
  • 另外,在PCAP中,IPv4标识为“IP”,IPv6标识为“IPv6”,还有“ARP”协议等等,需要单独处理。

提取五元组后,放在tuple中。本功能单独在packetRead()函数中实现,也在flowProcess()函数中使用。

五元组信息统计

对于同一个流,所有数据报的五元组信息都相同。此处的思路为统计出不相同的五元组信息为一个字典,key为五元组,value为五元组重复次数。

接上一单元,每次tuple提取后,将其append到flow_list的尾部。统计完后列表有重复项。建立空字典,flow_list.count(item)用于统计列表中每一个表项的重复次数,将item设为字典key,count的返回值设为字典的value,即可创建字典。

数据包划分

字典key的数量既为切分结果的子pcap数量,创建子pcap,读取原pcap中每个数据包信息,遇到匹配的塞进去,重复key次即可。

完整代码

# -*- coding: utf-8 -*-
#流:源端口号、目的端口号、协议号、源IP、目的IP

import scapy
from scapy.all import *
from scapy.utils import PcapReader
import os
import json

'''数据包五元组读取'''
def packetRead(p):
    packets=rdpcap(p) #提取pcap
    print(packets) #打印pcap信息
    flow_list=[]   #用于五元组信息统计
    '''提取五元组信息'''
    for data in packets:
        #data.show()  #展示当前类型包含的属性及值
        #协议:其中1,标识ICMP、2标识IGMP、6标识TCP、17标识UDP、89标识OSPF。
        #data.payload.name:'IP','IPV6','ARP'或者其他
        if data.payload.name == 'IP':
            try:
                five_tuple = "{}:{} {}:{} {}".format(data[IP].src,data.sport,data[IP].dst,data.dport,data.proto)
                flow_list.append(five_tuple)
            except AttributeError:
                continue
                print("AttributeError")
        elif data.payload.name == 'IPv6':
            try:
                five_tuple = "{}:{} {}:{} {}".format(data[IPv6].src,data.sport,data[IPv6].dst,data.dport,data.proto)
                flow_list.append(five_tuple)
            except AttributeError:
                continue
                print("AttributeError")
        elif data.payload.name == 'ARP':
            print('arp')
        else:
            print('不是ip ipv6 arp')
        
        print(five_tuple)
    #end for
    
'''将大数据包按流切分'''
def flowProcess(p):
    packets=rdpcap(p) #提取pcap
    print(packets) #打印pcap信息
    flow_list=[]   #用于五元组信息统计
    #用于统计不要的报文数
    arp = 0
    other = 0
    wrong_data = 0
    
    '''提取五元组信息'''
    for data in packets:
        #data.show()  #展示当前类型包含的属性及值
        #协议:其中1,标识ICMP、2标识IGMP、6标识TCP、17标识UDP、89标识OSPF。
        #data.payload.name:'IP','IPV6','ARP'或者其他
        if data.payload.name == 'IP':
            try:
                five_tuple = "{}:{} {}:{} {}".format(data[IP].src,data.sport,data[IP].dst,data.dport,data.proto)
                flow_list.append(five_tuple)
            except AttributeError:
                wrong_data = wrong_data+1
        elif data.payload.name == 'IPv6':
            try:
                five_tuple = "{}:{} {}:{} {}".format(data[IPv6].src,data.sport,data[IPv6].dst,data.dport,data.proto)
                flow_list.append(five_tuple)
            except AttributeError:
                wrong_data = wrong_data+1
        elif data.payload.name == 'ARP':
            arp = arp+1
        else:
            other = other+1
        
        flow_list.append(five_tuple)
    #end for
    print('arp:',arp,' other:', other, ' 数据包损坏:',wrong_data)
    
    '''统计流的数目与五元组信息,并保存txt'''
    i=0
    dicts = {} #用于统计每个五元组出现次数
    for item in flow_list:
        if flow_list.count(item)>=1:
            dicts[item]=flow_list.count(item) #统计五元组重复次数
            i = i+1
        if i%1000==0:#每1000次打印一下进度
            print('字典处理进度:',i/len(flow_list)*100,'%')
    #end for
    fileCreate(dicts,p,flow_list) #保存txt
    
    ''' 创建每个流的pcap '''
    #对每个五元组创建一个文件
    t_name1=p.split('.pcap')             #t_name1[0]  ./****/***
    t_name2=t_name1[0].split('./dataset') #t_name2[1]  /*** 
    os.mkdir('./dataset'+t_name2[1])
    total=len(dicts)      #统计流的数目
    for key in dicts.keys():
        #创建写入器
        writer = PcapWriter('./dataset'+t_name2[1]+t_name2[1]+'%d'%total+'.pcap', append = True)
        total = total-1
        if total%100 == 0:
            print('流切分进度:',(1-(total/len(dicts)))*100,'%') #打印当前进度
        for data in packets:
            if data.payload.name == 'IP':
                try:
                    #读取当前数据包的信息
                    t_tuple = "{}:{} {}:{} {}".format(data[IP].src,data.sport,data[IP].dst,data.dport,data.proto)
                    #比较信息
                    if t_tuple == key:
                        writer.write(data) #写入流
                        writer.flush()
                except AttributeError:
                    wrong_data = wrong_data+1
                    #print("AttributeError")
        writer.close()
    #end for


'''将五元组信息统计到文件中'''
def fileCreate(dicts,p,flow_list):
    #拆分拼接字符串 创建txt文件
    tlist=p.split('pcap')
    txt_name=tlist[0]+'txt'
    f = open(txt_name,'w')
    json_dicts = json.dumps(dicts,indent=1)
    f.write(json_dicts+"\n"+"the number of flows:"+str(len(dicts))+"\n"+"the number of packets:"+str(len(flow_list)))
    f.close()
    

#flowProcess函数用于将pcap按流切分成小pcap
#packetRead函数用于读取pcap中所有数据的五元组信息,可用于切分后验证。
#fileCreate函数保存统计好的五元组信息
#目录结构 ./dataset
if __name__=='__main__':
    #文件夹下数据集列表
    '''
    dirct = './dataset'
    dirList=[]
    fileList=[]
    files=os.listdir(dirct)  
    print('files:',files)
    print()
    '''

    #选择要切分的流的位置
    p ="./dataset/AppStore-web.pcap"
    pp="./dataset/AppStore-web/AppStore-web6.pcap"
    flow_list=flowProcess(p)
    packetRead(pp)

 

 

 

  • 5
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值