【问题标题】:How can I get the number of flows, the flows and the packets per flow from a .pcap file?如何从 .pcap 文件中获取流数、流数和每个流的数据包?
【发布时间】:2015-07-30 04:30:03
【问题描述】:
我正在处理大型 .pcap 数据包网络捕获(每个文件 > 5GB),并且我正在尝试将数据包分组到流中(例如,按 IP 源、IP 目标、源端口、目标端口和层分组4 协议)。我使用了一些软件工具,如 Scapy、CapLoader、tcpdump、tshark 等,但我找不到我想要的解决方案。
通过.pcap包文件我想知道流的数量,流然后找出哪些包属于每个流
知道最好的方法是什么吗?
如果解释不是很清楚,我很抱歉,我愿意提供任何进一步的解释或澄清。
非常感谢。
问候。
【问题讨论】:
标签:
networking
tcp
udp
network-protocols
pcap
【解决方案1】:
如果您愿意编写一些代码,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});
}
}