Networking 如何从.pcap文件中获取流的数量、流和每个流的数据包?

Networking 如何从.pcap文件中获取流的数量、流和每个流的数据包?,networking,tcp,udp,network-protocols,pcap,Networking,Tcp,Udp,Network Protocols,Pcap,我正在处理big.pcap数据包网络捕获(每个文件大于5GB),并尝试将数据包分组到流中(例如,按IP源、IP目标、源端口、目标端口和第4层协议分组)。我使用一些软件工具,如Scapy、CapLoader、tcpdump、tshark等,但我找不到我想要的解决方案 通过.pcap数据包文件,我想知道流的数量,流,然后找出属于每个流的数据包 你知道最好的方法是什么吗 我很抱歉,如果解释不是很清楚,我愿意提供任何进一步的解释或澄清 非常感谢 问候。如果您愿意编写一些代码,Perl脚本可能会很有用。在

我正在处理big.pcap数据包网络捕获(每个文件大于5GB),并尝试将数据包分组到流中(例如,按IP源、IP目标、源端口、目标端口和第4层协议分组)。我使用一些软件工具,如Scapy、CapLoader、tcpdump、tshark等,但我找不到我想要的解决方案

通过.pcap数据包文件,我想知道流的数量,流,然后找出属于每个流的数据包

你知道最好的方法是什么吗

我很抱歉,如果解释不是很清楚,我愿意提供任何进一步的解释或澄清

非常感谢


问候。

如果您愿意编写一些代码,Perl脚本可能会很有用。在Ask Wireshark,有人问了一个类似的问题,建议使用
Net::Pcap
和一些
NetPacket::*
包自己处理文件。这个答案有一个针对特定问题的示例脚本,但要获得您想要的信息并不难

编辑:我觉得这很有趣,所以我写了一个示例脚本

pcapFlows.pl

#!/usr/bin/perl

use strict;
use warnings;

use Net::Pcap;
use NetPacket::Ethernet qw(:types :strip);
use NetPacket::IP qw(:protos :strip);
use NetPacket::TCP;
use NetPacket::UDP;

my $pcap_file = $ARGV[0];

if (not $pcap_file) { 
    die("ERROR: please give pcap file name on the cli\n")
};

my $err = undef;

my %tracks;

# read data from pcap file.
my $pcap = pcap_open_offline($pcap_file, \$err) or die "Can't read $pcap_file : $err\n";
pcap_loop($pcap, -1, \&process_packet, \%tracks);

# close the device
pcap_close($pcap);

my $flowCount = 0;
# process tracks here

print "Flows\n";

foreach my $src (keys %tracks) {
    foreach my $dst (keys %{$tracks{$src}}) {
        foreach my $prot (keys %{$tracks{$src}{$dst}}) {
            $flowCount++;
            my $filename = "${src}_to_${dst}_$prot.pcap";
            print "$filename\n";

            my ($source, $dest) = ($src, $dst);

            $source =~ s/-/:/;
            $dest =~ s/-/:/;
            my $pktCount = 0;
            my $pcap_dumper = pcap_dump_open($pcap, $filename);
            foreach my $packet (@{$tracks{$src}{$dst}{$prot}{'packets'}}) {
                $pktCount++;
                pcap_dump($pcap_dumper, $packet->{'hdr'}, $packet->{'pkt'});
            }
            pcap_dump_flush($pcap_dumper);
            pcap_dump_close($pcap_dumper);

            print "$source <-> $dest ($pktCount)\n";
        }
    }
}

print "$flowCount flows found.\n";

sub process_packet {
    my ($user_data, $header, $packet) = @_;

    my $ip = NetPacket::IP->decode(eth_strip($packet));

    my $src_ip = $ip->{src_ip};
    my $dst_ip = $ip->{dest_ip};

    my ($prot, $payload);

    if ($ip->{proto} == IP_PROTO_TCP) {
        $prot = 'tcp';
        $payload = NetPacket::TCP->decode($ip->{data});
    } elsif ($ip->{proto} == IP_PROTO_UDP) {
        $prot = 'udp';
        $payload = NetPacket::UDP->decode($ip->{data});
    } else {
        return;
    }

    my $src_port = $payload->{src_port};
    my $dst_port = $payload->{dest_port};


    if (defined($user_data->{"$src_ip-$src_port"}) || !(defined($user_data->{"$src_ip-$src_port"}) || defined($user_data->{"$dst_ip-$dst_port"}))) {
        $user_data->{"$src_ip-$src_port"}{"$dst_ip-$dst_port"}{$prot}{'count'}++;
        push(@{$user_data->{"$src_ip-$src_port"}{"$dst_ip-$dst_port"}{$prot}{'packets'}}, {'hdr' => $header, 'pkt' => $packet});
    } elsif (defined($user_data->{"$dst_ip-$dst_port"})) {
        $user_data->{"$dst_ip-$dst_port"}{"$src_ip-$src_port"}{$prot}{'count'}++;
        push(@{$user_data->{"$dst_ip-$dst_port"}{"$src_ip-$src_port"}{$prot}{'packets'}}, {'hdr' => $header, 'pkt' => $packet});
    }
}
#/usr/bin/perl
严格使用;
使用警告;
使用Net::Pcap;
使用NetPacket::Ethernet qw(:类型:条带);
使用NetPacket::ipqw(:protos:strip);
使用NetPacket::TCP;
使用NetPacket::UDP;
我的$pcap_文件=$ARGV[0];
如果(不是$pcap_文件){
die(“错误:请在cli上提供pcap文件名\n”)
};
my$err=undef;
我的%tracks;
#从pcap文件读取数据。
my$pcap=pcap\u脱机打开($pcap\u文件,\$err)或死亡“无法读取$pcap\u文件:$err\n”;
pcap_循环($pcap,-1,\&process_数据包,\%tracks);
#关闭设备
pcap_关闭($pcap);
我的$flowCount=0;
#这里有进程跟踪
打印“流\n”;
foreach my$src(关键点%tracks){
foreach my$dst(键%{$tracks{$src}){
foreach my$prot(键%{$tracks{$src}{$dst}){
$flowCount++;
我的$filename=“${src}u到${dst}u$prot.pcap”;
打印“$filename\n”;
我的($source,$dest)=($src,$dst);
$source=~s/-/:/;
$dest=~s/-/:/;
我的$pktCount=0;
my$pcap\u dumper=pcap\u dump\u open($pcap,$filename);
foreach my$数据包(@{$tracks{$src}{$dst}{$prot}{'packets}}){
$pktCount++;
pcap_转储($pcap_转储程序,$packet->{'hdr'},$packet->{'pkt'});
}
pcap_转储_冲洗($pcap_转储器);
pcap_卸载_关闭($pcap_卸载机);
打印“$source$dest($pktCount)\n”;
}
}
}
打印“$flowCount流已找到。\n”;
子进程数据包{
我的($user\u data,$header,$packet)=@;
my$ip=NetPacket::ip->解码(eth_strip($packet));
my$src_ip=$ip->{src_ip};
my$dst_ip=$ip->{dest_ip};
我的($prot,$payload);
if($ip->{proto}==ip\u proto\u TCP){
$prot='tcp';
$payload=NetPacket::TCP->decode($ip->{data});
}elsif($ip->{proto}==ip_proto_UDP){
$prot='udp';
$payload=NetPacket::UDP->decode($ip->{data});
}否则{
返回;
}
my$src_port=$payload->{src_port};
my$dst_port=$payload->{dest_port};
if(已定义($user_data->{“$src_ip-$src_port”})|!(已定义($user_data->{“$src_ip-$src_port”})|已定义($user_data->{“$dst_ip-$dst_port”}))){
$user_data->{“$src_ip-$src_port”}{“$dst_ip-$dst_port”}{$prot}{'count'}++;
push({$user_data->{“$src_ip-$src_port”}{“$dst_ip-$dst_port”}{$prot}{'packets'}},{'hdr'=>$header,'pkt'=>$packet});
}elsif(已定义($user_data->{“$dst_ip-$dst_port”})){
$user_data->{“$dst_ip-$dst_port”}{“$src_ip-$src_port”}{$prot}{'count'}++;
push({$user_data->{“$dst_ip-$dst_port”}{“$src_ip-$src_port”}{$prot}{'packets'}},{'hdr'=>$header,'pkt'=>$packet});
}
}