#!/usr/sbin/perl # traffic-mon - Monitor ip traffic, and print high volume hosts # erco 10/21/99 1.00 # Typical output from tcpdump (spaces added for alignment) # # 188.10.6.8.1013 > 188.10.6.14.513: tcp 0 (DF) [tos 0x10] # 188.10.6.14.513 > 188.10.6.8.1013: tcp 118 (DF) [tos 0x10] # 188.10.6.102.1842 > 188.10.2.33.53: udp 48 # 188.10.2.33.53 > 188.10.6.102.1842: udp 114 # 188.10.6.102.18 > 188.10.2.33.53: udp 44 # 188.10.6.8.1013 > 188.10.6.14.513: tcp 0 (DF) [tos 0x10] # $| = 1; use Socket; my $cmd = "tcpdump -l -t -n -q"; my @arr; my ($src, $dst, $proto); my ($pcnt) = 0; my $timemark = time(); my $samplesecs = ( 5 * 60 ); # secs between pkt count rotations # OPEN TCPDUMP OUTPUT unless ( ( open ( FD, "$cmd|" ) ) ) { print STDERR "pipe failed for command '$cmd': $!"; exit(1); } while ( ) { if ( (++$pcnt) % 50 == 0 ) { my @out=sort{$traffic{$b}{pcnt}<=>$traffic{$a}{pcnt}}(keys(%traffic)); print "\033[2J\033[1;1H"; printf("%-8s %-8s %s\n", "Pkts", "5mins", "Hostname"); printf("%-8s %-8s %s\n", "----", "-----", "------------"); my $count = 0; foreach ( @out ) { printf("%-8d %-8d %-15s\n", $traffic{$_}{pcnt}, $traffic{$_}{pcnt5min}, IP2Hostname($_)); if ( ++$count > 20 ) { last; } } } # 5 MINS GONE BY? # Rotate out the current values, reset to zero # if ( time() > ( $timemark + $samplesecs ) ) { foreach ( keys ( %traffic ) ) { $traffic{$_}{pcnt5min} = $traffic{$_}{pcnt}; $traffic{$_}{pcnt} = 0; } $timemark = time(); } chomp(); @arr = split(); if ( $arr[0] !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) { next; } $src = sprintf("%d.%d.%d.%d", $1, $2, $3, $4); if ( $arr[2] !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) { next; } $dst = sprintf("%d.%d.%d.%d", $1, $2, $3, $4); $proto = $arr[3]; $traffic{$src}{pcnt}++; $traffic{$dst}{pcnt}++; } close(FD); # CONVERT IP ADDRESS TO HOSTNAME # $1 - ip address string, eg. "127.0.0.1" # sub IP2Hostname($) { my ($addr) = @_; # CHECK LOOKUP CACHE # If we already did the lookup, avoid the overhead from # the gethostbyaddr() call. # if ( defined( $G_ip2host{$addr} ) ) { return($G_ip2host{$addr}); } # DO A DNS LOOKUP my $iaddr = inet_aton($addr); my $name = gethostbyaddr($iaddr, AF_INET); if ( ! defined ( $name ) ) { $name = $addr; } # CACHE LOOKUP FOR LATER $G_ip2host{$addr} = $name; return( $name ); }