Beefy Boxes and Bandwidth Generously Provided by pair Networks RobOMonk
The stupid question is the question not asked
 
PerlMonks  

Perl and Net::Pcap

by rob_au (Abbot)
on May 31, 2002 at 07:57 UTC ( #170648=perltutorial: print w/ replies, xml ) Need Help??

 

Introduction

 

Throughout its history, Perl has always found a home in the suite of tools employed by system administrators in the maintenance, monitoring and administration of computer systems. As the diversity of demands and requirements placed upon computer systems has grown, so too has the requirement for system administrators to take full advantage of the tools at their disposal. In this respect, Perl has proven to be a most valuable asset to system administrators with an ever expanding base of diverse application and tool components available from the comprensive perl archive network (CPAN, http://www.cpan.org).

This tutorial is intended to introduce the reader to another such component available from CPAN, the Net::Pcap library. This module provides an interface for Perl to the Lawrence Berkeley National Laboratory Network Research Group's pcap library, which is a system-independent interface for user-level packet capture. This library provides a portable framework for low-level network monitoring and can be used for a variety of network monitoring functions including network statistics collection, security monitoring and network debugging. Thus, it is with a focus on network administration that this tutorial on the usage of Net::Pcap is presented.

 

Setting the Device

 

The first step in building an application or tool using Net::Pcap and the underlying libpcap library for network monitoring is to determine an available network interface which can be used for this monitoring network traffic. This device can be specified by the user for specific network monitoring, particularly on multi-homed machines, or can be determined by the lookupdev method from Net::Pcap.

The syntax of the lookupdev method is as follows:

$dev = Net::Pcap::lookupdev(\$err)

This method returns the name of a network device which can be used for monitoring network traffic - For example:

use Net::Pcap; use strict; my $err; my $dev = Net::Pcap::lookupdev(\$err); if (defined $err) { die 'Unable to determine network device for monitoring - ', $err; }

The string reference $err is passed as an argument to this method and is returned with an error description in the event of method failure. Upon method failure, the returned device name is also undefined.

A second method from Net::Pcap which warrants introduction at this point is lookupnet, which can be used to determine the network address and netmask for a device. This method is useful for the validation of a device name supplied for network monitoring by a user.

The syntax of the lookupnet method is as follows:

Net::Pcap::lookupnet($dev, \$net, \$mask, \$err)

This method returns the network address and netmask for the device specified, $dev. This method also follows the conventions of the underlying library of returning 0 for success and -1 for failure and as such error checking for this and other Net::Pcap functions may use the pseudo-reverse mentality of the die if .. idiom. For example:

my ($address, $netmask, $err); if (Net::Pcap::lookupnet($dev, \$address, \$netmask, \$err)) { die 'Unable to look up device information for ', $dev, ' - ', $err +; } print STDOUT "$dev: addr/mask -> $addr/$mask\n";

 

Capturing Packets

 

Once an appropriate network device has been determined, the process of packet capturing can be initiated. The Net::Pcap function open_live returns a packet capture descriptor which can be used for capturing and examining network packets.

The syntax of the open_live method is as follows:

$object = Net::Pcap::open_live($dev, $snaplen, $promisc, $to_ms, \$err +)

The $dev parameter specifies the network interface from which to capture network packets while the $snaplen and $promisc parameters specify the maximum number of bytes to capture from each packet and whether to put the interface into promiscuous mode, respectively. The latter of these parameters, the promiscuous mode, places the network card into a "snooping" mode where network packets not necessarily directed to the packet capturing machine are captured - In a non-switched network environment, this could effectively capture all network traffic! The $to_ms parameter specifies a read time-out for packet capturing in milliseconds - A $to_ms value of 0 captures packets until an error occurs while a value of -1 captures packets indefinitely.

The next step in the packet capture process is to establish a callback function for Net::Pcap to pass captured packets to for analysis and reporting - For this, the loop method of Net::Pcap is called:

Net::Pcap::loop($object, $count, \&callback_function, $user_data)

This method takes four mandatory arguments, the Net::Pcap object returned from the Net::Pcap::open_live method, $object, a numeric indicating the number of packets to capture, $count and a subroutine reference to the callback function. If the numeric passed to this function is negative, the Net::Pcap::loop will capture packets indefinitely (or until an error occurs if the $to_ms argument of the open_live method is set to 0). The fourth argument passed to this method with arbitrary data that is passed with the callback function with captured packets and can be used as a method to 'tag' captured packets or distinguish between several open packet capture sessions.

The callback function specified by the Net::Pcap::loop method receives the following arguments when called:

  • The $user_data string passed to the Net::Pcap::loop method.
  • A reference to a hash containing packet header information - The fields of this hash of packet header information are as follows:

    • len - the total length of the packet,
    • caplen - the captured length of the packet; this corresponds to the $snaplen argument passed to the Net::Pcap::open_live method
    • tv_sec - the seconds value of the packet timestamp
    • tv_usec - the microseconds value of the packet timestamp
  • A copy of the entire packet

An example of the callback function associated with packet capture may look like the following:

sub callback_function { my ($user_data, $header, $packet) = @_; ... }

 

Filtering Packets

 

While the methods described above, provide the means by which to capture all network traffic, the real power offered by the libpcap library is to selective filter network packets to monitor specific traffic. The filtering of network packets can be set through use of a filter language specific to the libpcap library - A description of this filter language can be found in the libpcap source code or on the tcpdump(8) man page. The use of this filter language for the selective capture of network packets does require some knowledge of TCP/IP networking and the underlying packet structure - The description of this filter language in detail is beyond the scope of this tutorial.

The Net::Pcap module provides methods for the compilation and setting of filters for network packet capture by means of the Net::Pcap::compile and Net::Pcap::setfilter methods.

The arguments of the Net::Pcap::compile method are as follows:

Net::Pcap::compile($object, \$filter_compiled, $filter_string, $optimi +se, $netmask)

This method will compile and check the filter specified in $filter_string for Net::Pcap object $object and return the compiled filter in the scalar $filter_compiled. The filter is optimised where possible if the $optimise variable is true. This function, like other Net::Pcap functions, returns 0 if successful or -1 if an error occurs.

The compiled filter string, $filter_compiled, can then be applied against the Net::Pcap object using the Net::Pcap::setfilter method - For example:

Net::Pcap::setfilter($object, $filter_compiled);

 

Decoding Captured Packets

 

Once packets have been captured using the Net::Pcap interface to libpcap, the next step is to decode this packets and make sense of the network packet data collected. This can be performed by constructing unpack templates for captured data or more easily through the NetPacket:: collection of modules. These modules each contain methods for extracting information from and about network packets, the most useful of which is arguably, the decode method - This method returns a hash of meta-data about the passed packet, specific to the packet type.

For example, the NetPacket::Ethernet::decode method will return the following information on captured ethernet packets:

  • src_mac - the source MAC address for the ethernet packet as a hex string
  • dest_mac - the destination MAC address for the ethernet packet as a hex string
  • type - the protocol type of the ethernet packet, for example, IP, ARP, PPP, SNMP
  • data - the data payload for the ethernet packet

Further information on each of the NetPacket:: modules and the information returned by the decode function can be found on their respective man pages.

In addition to this, each of the NetPacket:: modules also contain a strip method which simply returns the data payload of the network packet - This is useful when the network encapsulation is of little or no concern to your application.

 

Cleaning Up

 

Once finished capturing packets, the Net::Pcap::close method should be called to close the packet capture device. For example:

Net::Pcap::close($object)

 

Putting It All Together

 

The following example shows a way of putting all of the techniques described above and putting them to use for network administration. In this example, details of all TCP packets with the SYN header flag set captured by a machine will be reported - These network packets are used by a client in initiating a connection with a server and can be used to initiate denial of service attacks against a network host. For further information on TCP packet structure and the SYN header flag, see RFC793.

use Net::Pcap; use NetPacket::Ethernet; use NetPacket::IP; use NetPacket::TCP; use strict; my $err; # Use network device passed in program arguments or if no # argument is passed, determine an appropriate network # device for packet sniffing using the # Net::Pcap::lookupdev method my $dev = $ARGV[0]; unless (defined $dev) { $dev = Net::Pcap::lookupdev(\$err); if (defined $err) { die 'Unable to determine network device for monitoring - ', $e +rr; } } # Look up network address information about network # device using Net::Pcap::lookupnet - This also acts as a # check on bogus network device arguments that may be # passed to the program as an argument my ($address, $netmask); if (Net::Pcap::lookupnet($dev, \$address, \$netmask, \$err)) { die 'Unable to look up device information for ', $dev, ' - ', $err +; } # Create packet capture object on device my $object; $object = Net::Pcap::open_live($dev, 1500, 0, 0, \$err); unless (defined $object) { die 'Unable to create packet capture on device ', $dev, ' - ', $er +r; } # Compile and set packet filter for packet capture # object - For the capture of TCP packets with the SYN # header flag set directed at the external interface of # the local host, the packet filter of '(dst IP) && (tcp # [13] & 2 != 0)' is used where IP is the IP address of # the external interface of the machine. For # illustrative purposes, the IP address of 127.0.0.1 is # used in this example. my $filter; Net::Pcap::compile( $object, \$filter, '(dst 127.0.0.1) && (tcp[13] & 2 != 0)', 0, $netmask ) && die 'Unable to compile packet capture filter'; Net::Pcap::setfilter($object, $filter) && die 'Unable to set packet capture filter'; # Set callback function and initiate packet capture loop Net::Pcap::loop($object, -1, \&syn_packets, '') || die 'Unable to perform packet capture'; Net::Pcap::close($object); sub syn_packets { my ($user_data, $header, $packet) = @_; # Strip ethernet encapsulation of captured packet my $ether_data = NetPacket::Ethernet::strip($packet); # Decode contents of TCP/IP packet contained within # captured ethernet packet my $ip = NetPacket::IP->decode($ether_data); my $tcp = NetPacket::TCP->decode($ip->{'data'}); # Print all out where its coming from and where its # going to! print $ip->{'src_ip'}, ":", $tcp->{'src_port'}, " -> ", $ip->{'dest_ip'}, ":", $tcp->{'dest_port'}, "\n"; }

 

From Here

 

This tutorial has touched upon the basic functionality of the Net::Pcap module and how it can be used in network administration. Other features of this excellent module which have not been covered in tutorial include saving captured network packets to files and interface statistics handling - These features will be covered, if there is sufficient interest and demand, in a follow-up tutorial.

 

References

 

Blank-Edelman, David N. (2000) "Perl for System Administration" O'Reilly, ISBN 1-56592-609-9

Carstens, Tim (2002) "Programming with pcap" http://broker.dhs.org/pcap.html

Casado, Martin "Packet Capture with libpcap and other Low Level Network Tricks" http://www.dbaseiv.net/sockets/pcap/Tutorials/section1.html

 

Comment on Perl and Net::Pcap
Select or Download Code
Re: Perl and Net::Pcap
by nite_man (Deacon) on Apr 30, 2003 at 06:36 UTC
    Very very good article! It was usefull for me. Many thanks to rob_au.
    But I would like to add some information about using Net::Pcap under win32. You can use WinPcap - the Free Packet Capture Architecture for Windows and personal page of J-L Morel with consists an information about using Net::Pcap, Net::PcapUtils and ppm repository with those modules.
    Those tools will be usefull for porting Linux/Unix application under win32 (I do it at present :)) ).
          
    --------------------------------
    SV* sv_bless(SV* sv, HV* stash);
    
Re: Perl and Net::Pcap
by Anonymous Monk on Sep 23, 2003 at 17:22 UTC
    Great article, I guest its too late to ask for a follow-up, but it would have been nice...
Re: Perl and Net::Pcap
by Anonymous Monk on Jan 23, 2004 at 17:13 UTC
    Very useful article. I'd been struggling to understand the CPAN page but this article explained Net::Pcap very clearly. Thanks.
Wierd ip adresses using your example
by Anonymous Monk on May 21, 2008 at 23:01 UTC
    I used your example with the filter "my $filtro= "dst host 148.216.38.224"" and i get what i want in the most of the cases, but sometimes i get something like "14.165.148.216:0 -> 38.250.0.0:0". Nothing to do with my network. In Wireshark it didnt appear. What do you think is the problem? Thank you.
Re: Perl and Net::Pcap
by Anonymous Monk on Feb 27, 2010 at 01:09 UTC
    Hi, I've just started with perl so as a practice I thought of working with net::pcap. However lookupnet for my wlan returns an address which is equivalent to 192.168.100.0 instead of 192.168.100.100 and I guess that is the reason it can't snif the network packets. Can anyone point out what is it that I'm doing wrong Thanks
      Sorry guys that was y fault I read it wrongly as network address for device while its just network number
Re: Perl and Net::Pcap
by anderam (Initiate) on Apr 12, 2010 at 17:27 UTC

    Hi, first thank you for the introduction into tutorial.

    But I found one problem. Is there an option in Net::Pcap to work with nanopcap file format? I tried to open a nanopcap file, which can be easily opened with Wireshark, in my perl script using the Net::Pcap::open_offline() function and I'm getting standard error message "p is not of type pcap_tPtr at".

    I really need an advice on this one. Thanks in advance.

      Hi, this is very excellent article. I am bit struggling Can't locate object method "decode" via package "NetPacket::IP" (perhaps you for got to load "NetPacket::IP"?) at sysnp.pl line 83. with this error. Any Idea why? Many Thanks in Advance
        Did you load NetPacket::IP? Its not a trick question
Re: Perl and Net::Pcap
by dev2dev (Initiate) on Nov 12, 2010 at 11:12 UTC
    Thanks for the article. I didnt get luck yet to install Net-Pcap yet. I first tried to install the module but it said i need to install the wincap drives first. I downloaded adn installed wincap and installed this module 'successfully' . But looks likes it isn't successful because the script sill gives me compilation errors ' unable to find module Net::Pcap' and yes Its not there in C:\perl\bin or c:\perl\site\bin Can anyone help me pls

      You posted essentially the same thing moments ago here. Please don't spam the forum multiple times with the same issue, you've had an account here long enough to know better.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perltutorial [id://170648]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (17)
As of 2014-04-18 14:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (469 votes), past polls