【问题标题】:Analyzing pcap files using dpkt with python使用 dpkt 和 python 分析 pcap 文件
【发布时间】:2020-03-22 22:01:35
【问题描述】:

请我尝试使用 dpkt 在 python 中分析 pcap 文件。我想得到 1)唯一IP地址的数量, 2) 计算每个流的总字节数, 3) 每个流的数据包总数和 4) 每个流的平均数据包大小

如果有人可以帮助我解决上述问题的 python 代码,我将不胜感激。 谢谢

这就是我目前所做的

if __name__ == "__main__":

    # Packet Counters
    counter=0
    ipcounter=0
    nonipcounter=0    
    tcpcounter=0
    udpcounter=0
    httpcounter=0
    httpscounter=0
    ipv4counter=0
    ipv6counter=0

    # Subnet Dictionary
    subnets = {}

    # Open file

    # Packet processing loop
    for ts,pkt in dpkt.pcap.Reader(open('tesst.pcap','rb')):
        counter+=1

        # Parse ethernet packet
        eth=dpkt.ethernet.Ethernet(pkt)
        ip=eth.data       

        #check if IP packet or non-ip packet
        if eth.type == dpkt.ethernet.ETH_TYPE_IP or eth.type == dpkt.ethernet.ETH_TYPE_IP6:
            ipcounter = ipcounter + 1
        else:
            nonipcounter = nonipcounter + 1    

        # IPV6 packets
        if eth.type==dpkt.ethernet.ETH_TYPE_IP6: 
            ipv6counter+=1     


        # IPV4 packets
        elif eth.type==dpkt.ethernet.ETH_TYPE_IP:
            ipv4counter+=1

            # Extract destination
            string = socket.inet_ntoa(ip.dst)
            address = '.'.join(string.split(".")[:]) 
            if address in subnets: #increase count in dict
                subnets[address] = subnets[address] + 1
            else: #insert key, value in dict
                subnets[address] = 1            

            # TCP packets
            if ip.p==dpkt.ip.IP_PROTO_TCP: #ip.p == 6: 
                tcpcounter+=1
                tcp=ip.data

                # HTTP uses port 80
                if tcp.dport == 80 or tcp.sport == 80:
                    httpcounter+=1

                # HTTPS uses port 443
                elif tcp.dport == 443 or tcp.sport == 443:
                    httpscounter+=1


            # UDP packets
            elif ip.p==dpkt.ip.IP_PROTO_UDP: #ip.p==17:
                udpcounter+=1
                udp=ip.data


    # Print packet totals
    print ("Total number of ETHERNET packets in the PCAP file :", counter)
    print ("\tTotal number of IP packets :", ipcounter)
    print ("\t\tTotal number of TCP packets :", tcpcounter)
    print ("\t\t\tTotal number of HTTP packets :", httpcounter)
    print ("\t\t\tTotal number of HTTPS packets :", httpscounter)
    print ("\t\t\tTotal number of IPV6 packets :", ipv6counter)
    print ("\t\tTotal number of UDP packets :", udpcounter)    
    print ("\t\tTotal number of IPV4 packets :", ipv4counter)
    print ("\tTotal number of NON-IP packets :", nonipcounter)
    print ("--------------------------------------------------------------")
    other = counter-(arpcounter+httpcounter+httpscounter+ipv6counter)



    # Print addresses
    print ("Address \t \t Occurences")
    for key, value in sorted(subnets.items(), key=lambda t: int(t[0].split(".")[0])):
        print ("%s/16 \t = \t %s" %(key, value))

【问题讨论】:

  • 到目前为止你尝试过什么?你在哪里看过?
  • 到目前为止你尝试过什么?请发布您的代码和可能的数据示例。
  • 我能够输出IP包、TCP包、UDP包、IPV4和IPV6包的总数
  • @EricMPastore 我已经发布了我到目前为止所做的代码
  • @wobr 代码运行良好。我的代码可以输出 1)唯一 IP 地址的数量,2)计算每个流的字节总数,3)每个流的数据包总数和 4)每个流的平均数据包大小。我将立即发布输出

标签: python pcap


【解决方案1】:

我参与了您的初始代码并添加了一个初始功能,该功能按流收集 IP4-TCP 数据包,然后打印每个流的总字节数。您需要添加对 IP6 和 UDP 的处理以及收集剩余的统计信息,但希望这能让您最顺利地到达那里。这假设流完全由 4 元组 (src IP, src port, DST IP, DST port) 定义。在现实生活中,这些值可以(最终)在多个流中重复使用,所以这个假设并不完全成立,但同样希望这能让你继续前进。

[编辑]:

希望这符合您的要求:

import dpkt
from functools import reduce
import socket

tflows = {}
uflows = {}
ips = set()

def dumpFlow(flows, flow):
    print(f'Data for flow: {flow}:')
    bytes = reduce(lambda x, y: x+y,
                   map(lambda e: e['byte_count'], flows[flow]))
    duration = sorted(map(lambda e: e['ts'], flows[flow]))
    duration = duration[-1] - duration[0]
    print(f"\tTotal Bytes: {bytes}")
    print(f"\tAverage Bytes: {bytes / len(flows[flow])}")
    print(f"\tTotal Duration: {duration}")


for ts,pkt in dpkt.pcap.Reader(open('/tmp/tcpdump.pcap','rb')):
    eth=dpkt.ethernet.Ethernet(pkt)

    if eth.type==dpkt.ethernet.ETH_TYPE_IP:

        ip=eth.data

        # determine transport layer type
        if ip.p==dpkt.ip.IP_PROTO_TCP:
            flows = tflows
        elif ip.p==dpkt.ip.IP_PROTO_UDP:
            flows = **uflows**

        # extract IP and transport layer data
        src_ip = socket.inet_ntoa(ip.src)
        src_port = ip.data.sport
        dst_ip = socket.inet_ntoa(ip.dst)
        dst_port = ip.data.dport

        # keeping set of unique IPs
        ips.add(src_ip)
        ips.add(dst_ip)

        # store flow data
        flow = sorted([(src_ip, src_port), (dst_ip, dst_port)])
        flow = (flow[0], flow[1])
        flow_data = {
            'byte_count': len(eth),
            'ts': ts
        }

        if flows.get(flow):
            flows[flow].append(flow_data)
        else:
            flows[flow] = [flow_data]


print(f'Total TCP flows: {len(tflows.keys())}')
print(f'Total UDP flows: {len(uflows.keys())}')
print(f'Total IPs: {len(ips)}')

for k in tflows.keys():
    dumpFlow(tflows, k)
for k in uflows.keys():
    dumpFlow(uflows, k)

【讨论】:

  • 非常感谢,这非常有用。有没有办法也可以一起计算?就像,计算所有流以输出类似 6 个流。输出格式为单向流 = (src_ip, src_port, dst_ip, dst_port)。例如:流数据:('172.17.84.129',53721,'64.233.183.188',5228):总字节数:123 流数据:('64.233.183.188',5228,'172.17.84.129',53721):总字节数:358 流数据:('162.125.19.131',443,'172.17.84.129',53756):总字节数:760 流数据:('172.17.84.129',53756,'162.125.19.131',443 ): 总字节数:2347
  • 我刚刚发现了一些关于字节数的信息。该代码未输出正确的总字节数。如果您不介意在单个数据包上尝试一下,看看我在说什么。提前致谢
  • 好吧,我进步了一点,它只能输出单个数据包的实际字节数,不能输出更多数据包。虽然仍在努力。请,如果你解决它,请分享。谢谢!!!!
  • 那太好了!!!一个来自你。当我昨天注意到它时,我已经解决了。我在使用以下代码时遇到问题 1) 计算 pcap 文件中 TCP 流的数量 2) 计算 pcap 文件中 UDP 流的数量 3) 计算唯一 IP 地址的数量 4) 计算每个数据包的总数流 5) 计算每个流的平均数据包大小 6) 计算每个流的持续时间。从我上面的代码中,我无法实现这一点。我知道我要求太多,但我非常感谢您的帮助。非常感谢!!!!!!
  • 是的。太感谢了!您的帮助。真的很完美!!!
猜你喜欢
  • 2011-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-07
  • 2012-04-29
  • 2018-09-22
  • 2013-08-17
  • 1970-01-01
相关资源
最近更新 更多