Saturday, August 23, 2008

Summarise Netstat Inbound and Outbound Traffic

If we are managing a busy server with tonnes of inbound and outbound network connections, the below script may help you to summarise the 'netstat' details.

If connection tuple's (localhost:localport - remotehost:remoteport) localport is one of the listening ports, we can say that the connection is an inbound, else outbound. At first I tried to use ephemeral port to figure out the in/out bound, but find it not very reliable 'cos software can listen to a high port too. Also, you need to run netstat with -n (Show network addresses as numbers) in order to figure out the numeric port number.

The "getlisten" shell function is a trick that I normally used to dynamically create the AWK BEGIN content. In this case, I parse the "netstat" output and set the "listen" array variable in AWK to 1. This function will be invoked by the shell (not inside AWK) and shell will 'glue' them together with the AWK code. '`getlisten`' - first single quote is to temporary terminate AWK, follow by backquote to run the shell function, then open a single quote to continue the AWK. Remember no space is allowed between the single quote and backquote.

#! /bin/sh
#
# Summary netstat information by inbound and outbound traffic




TMPFILE=/tmp/.netstat-$$
trap "rm -f $TMPFILE" 0 1 2 3 9 15


netstat -a -finet -Ptcp > $TMPFILE
timestamp=`date '+%Y%m%dT%H%M%S'`


#
# shell function to create AWK BEGIN block for all the listening ports
# eg. listen["123"]=1;
#
getlisten()
{
 awk '$NF=="LISTEN" {n=split($1,a,".");printf("listen[\"%s\"]=1;",a[n])}' $TMPFILE
}



nawk -v timestamp=$timestamp '

function getport (hostport, n) {
 n=split(hostport,a,".")
 return a[n]
}

function gethost (hostport, n, h) {
 n=split(hostport,a,".")
 h=a[1]
 for(i=2;i<n;++i) {
  h=sprintf("%s.%s",h,a[i])
 }
 return h
}

BEGIN {'`getlisten`'}

NR>4 && $NF!~/(IDLE|BOUND|LISTEN)$/ {
 lh=gethost($1)
 lp=getport($1)
 rh=gethost($2)
 rp=getport($2)

 # if local port is one of the listen ports
 #   is inbound
 # else
 #   is outbound
 if ( listen[lp] == 1 ) {
  key=sprintf("%s:%s<-%s %s ",lh,lp,rh,$NF)
  ++inbound[key]
 } else {
  key=sprintf("%s->%s:%s %s ",lh,rh,rp,$NF)
  ++outbound[key]
 }
}

END {
 for(i in inbound) {
  print timestamp, i, inbound[i]
 }
 for(i in outbound) {
  print timestamp, i, outbound[i]
 }
}
' $TMPFILE

Sample output:

$ ./n.sh
20080822T163621 sgehost:sge_qmaster<-sgehost ESTABLISHED  1
20080822T163621 sgehost:ldap<-sgehost ESTABLISHED  12
20080822T163621 sgehost:ssh<-remote_server ESTABLISHED  1
20080822T163621 sgehost:sge_qmaster<-sgeexec2 ESTABLISHED  1
20080822T163621 sgehost:sge_qmaster<-sgeexec0 ESTABLISHED  1
20080822T163621 sgehost:sge_qmaster<-sgeexec1 ESTABLISHED  1
20080822T163621 sgehost->sgehost:ldap ESTABLISHED  12
20080822T163621 sgehost->sgehost:sge_qmaster ESTABLISHED  1

BTW, this script is developed on a Solaris platform.

Labels: , ,

0 Comments:

Post a Comment

<< Home