Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Re: TCP session recreation from pcap files

by Khen1950fx (Canon)
on Jul 12, 2009 at 06:19 UTC ( #779317=note: print w/replies, xml ) Need Help??

in reply to TCP session recreation from pcap files

I've looked at the documentation for Net::Analysis. It's confusing and clearly obfuscated. I also tried the one-liners; however, none of them worked:-). Since you are new to Perl, I think that you should experiment with Net::Pcap for a while. It has some quirks, but I've managed to get it to work on occasion. You could start with pcapdump. It had some problems, but I fixed it and put it below for you.

Update: For a one-liner, try something like:

perl /path/to/pcapdump -c 1000 -i eth0 -s 512 -w /path/to/tcpdump

#!/usr/bin/perl use strict; use Data::Hexdumper; use File::Basename; use Getopt::Long qw(:config no_auto_abbrev); use Net::Pcap qw(:functions); use NetPacket::Ethernet qw(:types); use NetPacket::IP qw(:protos); use NetPacket::ICMP; use NetPacket::TCP; use NetPacket::UDP; use Pod::Usage; use Socket qw(inet_ntoa); $::PROGRAM = basename($0); $::VERSION = "0.01"; # globals my $dumper = undef; my %icmp = ( ICMP_ECHO => "echo", ICMP_ECHOREPLY => "echo-reply", ICMP_IREQ => "ireq", ICMP_IREQREPLY => "ireq-reply", ICMP_MASREQ => "mask", ICMP_MASKREPLY => "mask-reply", ICMP_PARAMPROB => "param-prob", ICMP_REDIRECT => "redirect", ICMP_ROUTERADVERT => "router-advert", ICMP_ROUTERSOLICIT => "router-solicit", ICMP_SOURCEQUENCH => "source-quench", ICMP_TIMXCEED => "time-exceeded", ICMP_TSTAMP => "timestamp", ICMP_TSTAMPREPLY => "timestamp-reply", ICMP_UNREACH => "unreachable", ); MAIN: { run(); } sub run { $|++; # get options my %options = ( count => 10, promisc => 0, snaplen => 256, timeout => 10, ); GetOptions(\%options, qw{ help|h! version|V! count|c=i interface|i=s promisc|p! snaplen|s=i writeto|w=s }) or pod2usage(); pod2usage({ -verbose => 2, -exitval => 0 }) if $options{help}; print "$::PROGRAM v$::VERSION\n" if $options{version}; my ($err, $net, $mask, $filter); my $dev = $options{interface} || lookupdev(\$err); my $filter_str = join " ", @ARGV; # open the interface my $pcap = open_live($dev, @options{qw(snaplen promisc timeout)}, +\$err) or die "fatal: can't open network device $dev: $err ", "(do you have the privileges?)\n"; if ($filter_str) { # compile the filter compile($pcap, \$filter, $filter_str, 1, 0) == 0 or die "fatal: filter error\n"; setfilter($pcap, $filter); } if ($options{writeto}) { $dumper = dump_open($pcap, $options{writeto}) or die "fatal: can't write to file '$options{writeto}': $! +\n"; } # print some information about the interface we're currently using lookupnet($dev, \$net, \$mask, \$err); print "listening on $dev (", dotquad($net), "/", dotquad($mask), " +)", ", capture size $options{snaplen} bytes"; print ", filtering on $filter_str" if $filter_str; print $/; # enter the main loop loop($pcap, $options{count}, \&process_packet, ''); pcap_close($pcap); } sub process_packet { my ($user_data, $header, $packet) = @_; my ($proto, $payload, $src_ip, $src_port, $dest_ip, $dest_port, $f +lags); printf "packet: len=%s, caplen=%s, tv_sec=%s, tv_usec=%s\n", map { $header->{$_} } qw(len caplen tv_sec tv_usec); # dump the packet if asked to do so pcap_dump($dumper, $header, $packet) if $dumper; # decode the Ethernet frame my $ethframe = NetPacket::Ethernet->decode($packet); if ($ethframe->{type} == ETH_TYPE_IP) { # decode the IP payload my $ipframe = NetPacket::IP->decode($ethframe->{data}); $src_ip = $ipframe->{src_ip}; $dest_ip = $ipframe->{dest_ip}; if ($ipframe->{proto} == IP_PROTO_ICMP) { my $icmpframe = NetPacket::ICMP->decode($ipframe->{data}); $proto = "ICMP"; $payload = $icmpframe->{data}; } elsif ($ipframe->{proto} == IP_PROTO_TCP) { my $tcpframe = NetPacket::TCP->decode($ipframe->{data}); $proto = "TCP"; $src_port = $tcpframe->{src_port}; $dest_port = $tcpframe->{dest_port}; $payload = $tcpframe->{data}; $flags = flags_of($tcpframe->{flags}); } elsif ($ipframe->{proto} == IP_PROTO_UDP) { my $udpframe = NetPacket::UDP->decode($ipframe->{data}); $proto = "TCP"; $src_port = $udpframe->{src_port}; $dest_port = $udpframe->{dest_port}; $payload = $udpframe->{data}; } printf "IP:%s %s:%d -> %s:%d (%s)\n", $proto, $src_ip, $src_port, $dest_ip, $dest_port, $flags; print hexdump(data => $payload, start_position => 0) if length + $payload; print $/; } } sub flags_of { my ($flags) = @_; my @strarr = (); push @strarr, "urg" if $flags & URG; push @strarr, "ack" if $flags & ACK; push @strarr, "psh" if $flags & PSH; push @strarr, "fin" if $flags & FIN; push @strarr, "syn" if $flags & SYN; push @strarr, "rst" if $flags & RST; push @strarr, "ece" if $flags & ECE; push @strarr, "cwr" if $flags & CWR; return join ",", @strarr } sub dotquad { return inet_ntoa( pack("I", $_[0]) ) } __END__ =head1 NAME pcapdump - Dump packets from the network =head1 SYNOPSIS pcapdump [-c count] [-i interface] [-s snaplen] [-w file] [express +ion] pcapdump --help pcapdump --version =head1 OPTIONS =over =item B<-c>, B<--count> I<N> Exit after receiving I<N> packets. =item B<-i>, B<--interface> I<device> Listen on the specified interface. If unspecified, the program will us +e the interface returned by C<pcap_lookupdev()>. =item B<-s>, B<--snaplen> I<L> Capture I<L> bytes of data for each packet. Defaults to 256. =item B<-w>, B<--writeto> I<file> =back =head1 DESCRIPTION B<pcapdump> mimics the very basic features of B<tcpdump(1)> and provid +es a good example of how to use C<Net::Pcap>. =head1 AUTHOR SE<eacute>bastien Aperghis-Tramoni, E<lt>sebastien@aperghis.netE<gt> =head1 COPYRIGHT Copyright (C) 2005, 2006, 2007, 2008 SE<eacute>bastien Aperghis-Tramon +i. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut

Replies are listed 'Best First'.
Re^2: TCP session recreation from pcap files
by narcos (Initiate) on Jul 14, 2009 at 11:13 UTC
    Ah thanks very much for the help Khen. I played a little with pcapdump. Seems similar to tcpdump and I'd been using that. So, the situation I'm in is that I already have a large number of dump files from a large network and I want to do some analysis on them (as opposed to capturing new data with something like pcapdump).

    Whilst I have managed to script some stuff to extract individual packet information (headers+payload) from pcap files:

    use strict; use Net::TcpDumpLog; use NetPacket::IP qw(:strip); use NetPacket::TCP qw(:strip); my $log = Net::TcpDumpLog->new(); $log->read($ARGV[0]); my @Indexes = $log->indexes; my $index; my ($length_orig,$length_incl,$drops,$secs,$msecs); my $data; print ("IP SRC,IP DST, IP LENGTH, IP TOS, IP TTL, IP Offset, TCP ACK, +TCP flags, TCP Winsize, TCP Chksum, TCP URG\n"); foreach $index (@Indexes) { ($length_orig,$length_incl,$drops,$secs,$msecs) = $log->header($in +dex); $data = $log->data($index); my ($ether_dest,$ether_src,$ether_type,$ether_data) = unpack('H12H +12H4a*',$data); my $ip_obj = NetPacket::IP->decode($ether_data); my $tcp_obj = NetPacket::TCP->decode( $ip_obj->{data}); print ("$i $ip_obj->{src_ip} ($tmpIPs),$ip_obj->{dest_ip} ($tmpIP +d),$ip_obj->{len},$ip_obj->{tos},$ip_obj->{ttl},$ip_obj->{foffset},$t +cp_obj->{acknum},$tcp_obj->{flags}, $tcp_obj->{winsize}, $tcp_obj->{c +ksum}, $tcp_obj->{urg}\n");
    ...I'm struggling a bit to recreate the sessions in a nice way. I figured out with that Net::Analysis tool that the following command:
    $perl -MNet::Analysis -e main TCP,v=7 google.dump
    gives the output:
    = ( 0 23:28:09.091264 *AP + SEQ:4094724362 ACK:3316076611 1072b ====[23:28:09.091264] tcp session start [ -> 209. +85.227.99:80] ==[23:28:09.091264] [Mono from] 0.000000s, + 1pkts, 1072b = ( 1 23:28:09.119041 *A + SEQ:3316076611 ACK:4094725434 1368b = ( 2 23:28:09.119097 _A [......] ====[--:--:--.------] tcp session end [ +7.99:80]
    i.e. it's reconstructing sessions as well as monologues within each session and listing each packet. Now what I really want to do is to figure out how to 'code' the above command such that I can tweak it. Instead of outputting each packet to the console, for example, I'd like to insert it into a database. Also I'd like additional header information.

    The kludge approach I'm about to take is to dump the whole output to a file and then parse it with another script, and then try and match each packet in the Net::Analysis output to each packet in my above scripts output. Not so ideal...

    Thanks and sorry for rambling!

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://779317]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (2)
As of 2018-02-21 11:40 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (279 votes). Check out past polls.