antioch has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to develop a program that will listen to a local port and grab all data going through it (this is to monitor some ports). Pretty much like a small packet sniffer. I'm not really sure what I should use to connect to the local port (Net::Telnet, IO::Socket, etc.) and how I would go about gettin all the data going through it (perhaps into strings).

If anyone could please lead me in the right direction, that would be greatly appreciated. Thanks.

antioch

20040417 Edit by Corion: Moved from PMD to Seekers of Perl Wisdom

Replies are listed 'Best First'.
Re: Working with ports in Perl
by Corion (Patriarch) on Apr 17, 2004 at 16:51 UTC

    Depending on the nature of your data, there are two ways, easy and hard. I interpret your question that way, that you want to have a proxy that sits in the middle between your program and the outside network.

    The easy way is if you only want to intercept HTTP data. Then you can use HTTP::Proxy.

    The hard way is if you want to intercept other data. Then you have to use Net::PCap together with Net::PCapUtils, which allows you to sniff and alter any TCP transmission. There are some other more convenient modules, like Net::Divert and Net::ProxyMod (by Stephanie Wehner), but these module are for BSD(-like) systems only, as they use features only found there.

      Another libpcap related module you can use in Net::RawIP. It has a more OO based interface, and the documentation seems to be a little more easy to follow and quicker to get started with.

Re: Working with ports in Perl
by gmpassos (Priest) on Apr 17, 2004 at 17:30 UTC
    How about something already done?! ;-P
    #!/usr/bin/perl $|=1; use IO::Socket ; use IO::Select ; my $redirect_host = 'smtp.fln.terra.com.br' ; my $redirect_port = 25 ; my $local_port = $redirect_port ; my $accept_externals = 0 ; my $log_file = 'log.txt' ; ###################################################################### +########## my $server = IO::Socket::INET->new( Listen => 5, ( !$accept_externals ? (LocalAddr => 'localhost') : () ) , LocalPort => $local_port , Proto => 'tcp' , Blocking => 1 , ) ; my $client = $server->accept; my $remote = new IO::Socket::INET( PeerAddr => $redirect_host , PeerPort => $redirect_port , Proto => 'tcp', Timeout => 30) ; my %socks = ( $remote => 'SRV' , $client => 'CLT' , ) ; my %redir = ( $remote => $client , $client => $remote , ) ; open (LOG,">$log_file") ; my $sel = select(LOG) ; $|=1; select($sel); print "Waiting client...\n" ; my $can_read = IO::Select->new( $remote , $client ); my @has_buf ; while( @has_buf = $can_read->can_read(1) ) { foreach my $has_buf_i ( @has_buf ) { my $redir = $redir{$has_buf_i} ; my $buffer ; my $sel = IO::Select->new($has_buf_i) ; while( $sel->can_read(0.1) ) { read($has_buf_i, $buffer , 1 , length($buffer) ) ; if ($buffer =~ /\n$/s ) { last ;} } if ($buffer ne '') { print $redir $buffer ; print "$socks{$has_buf_i}>> $buffer" ; print LOG "$socks{$has_buf_i}>> $buffer" ; } } }
    This script will listen and redirect to some port, and log the data to a file. Just edit the variables in the top and run. I used that to check the security of the SMTP server of my ISP.

    Graciliano M. P.
    "Creativity is the expression of the liberty".