Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading packets with Linux::TunTap

I've put together a perl script that reads packets into userspace via Linux::TunTap, and it all seems to work fine:

#!/usr/bin/perl
use warnings;
use strict;
use Linux::TunTap;

$tun = new Linux::TunTap(NAME => 'localtun')
or die "Couldn't connect to IF\n";

while (my $packet = $tun->get_raw()) {
        print Dumper($packet);
}

Now the question is: How do I turn the string representing the raw IP packet as read from the tuntap device into a proper datastructure for processing? In particular I'm after the source, destination, and sequence number.

Obviously, the raw IP packet isn't very human readable in its original format. Here's the output after sending a ping through the tuntap interface:

{{{�}/��8V�| !"#$%&'()*+,-./0123456ET��@@4

How do I proceed from here to be able to process this data programatically?

like image 568
Jarmund Avatar asked Sep 27 '15 00:09

Jarmund


1 Answers

Based on the comment made by SteffenUlrich, I had a look at NetPacket::IP, which did the trick for me through its decode() method. It worked pretty much out of the box after baking it into my code, with the only caveat being that the first four bytes has to go from the raw data (see lazy regex below), as these bytes form an additional header added by the TunTap layer.

My code now looks like this, and works as intended:

#!/usr/bin/perl
use warnings;
use strict;
use Linux::TunTap;
use NetPacket::IP;

$tun = new Linux::TunTap(NAME => 'localtun')
or die "Couldn't connect to IF\n";

while (my $rawdata = $tun->get_raw()) {
        $rawdata =~ s/^....//;  # Using regex to strip 4 bytes, because I'm lazy 
        my $packet = NetPacket::IP->decode($rawdata);
        print "$packet->{id} $packet->{src_ip} -> $packet->{dest_ip} $packet->{proto} $packet->{len}\n";
}

The above code prints the sequence, source IP, destination IP, protocol number, and packet length.

like image 103
Jarmund Avatar answered Oct 23 '22 04:10

Jarmund