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

时间:2015-05-18 15:23:36

标签: networking tcp udp network-protocols pcap

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

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

知道最好的方法是什么?

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

非常感谢。

问候。

1 个答案:

答案 0 :(得分:0)

如果您愿意编写一些代码,Perl脚本可能会有用。在Ask Wireshark,有人问了一个类似的问题,并got a response建议使用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});
    }
}