Saturday, September 15, 2012

自家用 ipfw log 統計

雖然有 security/ipfwcount 好用, 但是總想可以自由的分析 ipfw.log. 所以就寫了以下的 stupid script. 哈哈 ... 但是它可以用.

#!/usr/local/bin/bash
##
##  FreeBSD ipfw log analyzer
##

PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/sbin:$PATH"

TS=`date +"%s"`
TMPFILE="/tmp/ana_ipfw-$TS"
TMPFILEsort="/tmp/ana_ipfw_sort-$TS"
LC_ALL=C
LANG=C

### Default options
datelimit=no
portlimit=no
iplimit=no
verbose=no
sorted=no
onlydata=no
datestr=""
logfile="/var/log/ipfw.log"

### Help
usage () {
 echo "Usage: $0 [-p] [-i] [-v] [-s] [-o] [-d date_limit] [filename]"
 echo "   -p  port analysis"
 echo "   -i  IP address analysis"
 echo "   -d  date format"
 echo "   +DDAY   from DDAY to today"
 echo "   +-DDAY  DDAY days ago"
 echo "   YYYYMMDD-YYYYMMDD  from first YYYYMMDD to last YYYYMMDD"
 echo "   total   all data records in the log file"
 echo "   -s  sorted by count"
 echo "   -o  only data and disable verbose"
 echo "   -v  enable verbose messages"
 echo "   filename default : /var/log/ipfw.log"
}
if [ $# -eq 0 ]; then
 usage
 exit 1
fi

### Get arguments
args=`getopt dpivso $*`

if [ $? != 0 ]; then
 echo "$0:ERROR"
 exit 2
fi

set -- $args

for arg
do
 case "$arg" in
  -d )  datelimit=yes; shift ;;
  -p )  portlimit=yes; shift ;;
  -i )  iplimit=yes; shift ;;
  -v )  verbose=yes; shift ;;
  -s )  sorted=yes; shift ;;
  -o )  onlydata=yes; shift ;;
  -- )  datestr=$2; shift; shift ;;
 esac
done

if [ $datelimit == "no" ]; then
 if [ ! -z $datestr ]&&[ -f $datestr ]; then
  logfile=$datestr
 fi
else
 if [ ! -z $datestr ]&&[ ! -z $1 ]; then
  logfile=$1
 fi
fi

if [ ! -f $logfile ]; then
 echo "Error : Log file $logfile does not existed."
 exit 1
fi

if [ $onlydata == "yes" ]; then
 verbose=no
fi

### For debug
if [ $verbose == "yes" ]; then
 echo "Parameters"
 echo $args
 echo "Date $datelimit($datestr) Port $portlimit IP $iplimit Verbose $verbose Sort $sorted Logfile $logfile"
 echo ""
fi

### Generate date limitation
if [ $datelimit == "no" ]; then
 dtmp="0"
 datearray=($dtmp)
else
 if [ ! -z `echo $datestr | awk 'BEGIN { FS = "+" } ; { print $2 }'` ]; then
  if [ ! -z `echo $datestr | awk 'BEGIN { FS = "+" } ; { print $2 }' | awk 'BEGIN { FS = "-" } ; { print $2 }'` ]; then
   datearray=(`echo $datestr | awk 'BEGIN { FS = "+" } ; { print $2 }' | awk 'BEGIN { FS = "-" } ; { print $2 }'`)
  else
   i=`echo $datestr | awk 'BEGIN { FS = "+" } ; { print $2 }'`
   dtmp=""
   for((; i >= 0; i--))
   do
    dtmp="$dtmp $i"
   done
   datearray=($dtmp)
  fi
 elif [ "$datestr" == "total" ]; then
  datestr="total"
 elif [ -z $datestr ]; then
  dtmp="0"
  datearray=($dtmp)
 else
  if [[ $datestr != *[!0-9\-]* ]]; then
   bdate=`echo $datestr | awk 'BEGIN { FS = "-" } ; { print $1 }'`
   edate=`echo $datestr | awk 'BEGIN { FS = "-" } ; { print $2 }'`
  else
   bdate=`date +"%Y%m%d"`
   edate=`date +"%Y%m%d"`
  fi

  todayts=`date -j "+%s"`
  bdatets=`date -j -f "%Y%m%d" "$bdate" "+%s"`
  edatets=`date -j -f "%Y%m%d" "$edate" "+%s"`

  if [ $bdatets -gt $todayts ]; then
   echo "Error : $bdate is future. I can not analyze it."
   exit 1
  else
   ib=`expr \( $todayts - $bdatets \) / 86400`
  fi
  if [ $edatets -gt $todayts ]; then
   if [ $verbose == "yes" ]; then
    echo "Warning : $edate is future. But I can replace it with today("`date +"%Y%m%d"`")."
    echo ""
   fi
   ie=0
  else
   ie=`expr \( $todayts - $edatets \) / 86400`
  fi

  dtmp=""
  for((i = $ib; i >= $ie; i--))
  do
   dtmp="$dtmp $i"
  done
  datearray=($dtmp)
 fi
fi

### Create tmp file
if [ $verbose == "yes" ]; then
 echo "Create $TMPFILE"
 echo ""
fi
touch $TMPFILE

### Get log
if [ $verbose == "yes" ]; then
 echo "Get log from $logfile"
fi
if [ $datelimit == "no" ]; then
 if [ $verbose == "yes" ]; then
  date +"%b %e"
 fi
 keyfilter=`date +"%b %e"`
 grep "$keyfilter" $logfile >> $TMPFILE
elif [ "$datestr" == "total" ]; then
 cat $logfile > $TMPFILE
else
 for dnum in ${datearray[@]}
 do
  if [ $verbose == "yes" ]; then
   date -v-${dnum}d +"%b %e"
  fi
  keyfilter=`date -v-${dnum}d +"%b %e"`
  grep "$keyfilter" $logfile >> $TMPFILE
 done
fi
if [ $verbose == "yes" ]; then
 echo ""
fi

if [ $verbose == "yes" ]; then
 echo "Count lines in $TMPFILE"
 wc -l $TMPFILE
 echo ""
fi

### Port Analysis
if [ $portlimit == "yes" ]; then
 if [ $sorted == "yes" ]; then
  rm -f $TMPFILEsort
  touch $TMPFILEsort
 fi

 if [ $onlydata == "no" ]; then
  echo "[[[ Port Analysis ]]]"
  printf "%12s\t%12s\n" "Port Number" "Count"
  printf "%12s\t%12s\n" "------------" "--------"
 fi
 for portnum in `cat $TMPFILE | awk 'BEGIN { FS = " " } ; { if( $11=="\-\>" ){ split($12, p, ","); print p[1] } else { print $11 } }' | grep ":" | awk 'BEGIN { FS = ":" } ; { print $2 }' | sort -u -n`
 do
  if [ $sorted == "yes" ]; then
   printf "%12s\t%12s\n" "$portnum" `cat $TMPFILE | awk 'BEGIN { FS = " " } ; { if( $11=="\-\>" ){ split($12, p, ","); print p[1] } else { print $11 } }' | grep ":" | awk 'BEGIN { FS = ":" } ; { print $2 }' | grep $portnum | wc -l` >> $TMPFILEsort
  else
   printf "%12s\t%12s\n" "$portnum" `cat $TMPFILE | awk 'BEGIN { FS = " " } ; { if( $11=="\-\>" ){ split($12, p, ","); print p[1] } else { print $11 } }' | grep ":" | awk 'BEGIN { FS = ":" } ; { print $2 }' | grep $portnum | wc -l`
  fi
 done
 if [ $sorted == "yes" ]; then
  cat $TMPFILEsort | awk 'BEGIN { FS = " " } ; { printf ( "%12s\t%12s\n", $1, $2) }' | sort -rgk2 > /tmp/ttt-$TS
  cat /tmp/ttt-$TS > $TMPFILEsort
  rm -f /tmp/ttt-$TS
  cat $TMPFILEsort
 fi
fi

### Client IP Analysis
if [ $iplimit == "yes" ]; then
 if [ $sorted == "yes" ]; then
  rm -f $TMPFILEsort
  touch $TMPFILEsort
 fi

 if [ $onlydata == "no" ]; then
  echo "[[[ Client IP Analysis ]]]"
  printf "%16s\t%12s\n" "IP Address" "Count"
  printf "%16s\t%12s\n" "----------------" "--------"
 fi
 for ipaddr in `cat $TMPFILE | awk 'BEGIN { FS = " " } ; { print $10 }' | grep ":" | awk 'BEGIN { FS = ":" } ; { print $1 }' | sort -u -n`
 do
  if [ $sorted == "yes" ]; then
   printf "%16s\t%12s\n" "$ipaddr" `cat $TMPFILE | awk 'BEGIN { FS = " " } ; { print $10 }' | grep ":" | awk 'BEGIN { FS = ":" } ; { print $1 }' | grep $ipaddr | wc -l` >> $TMPFILEsort
  else
   printf "%16s\t%12s\n" "$ipaddr" `cat $TMPFILE | awk 'BEGIN { FS = " " } ; { print $10 }' | grep ":" | awk 'BEGIN { FS = ":" } ; { print $1 }' | grep $ipaddr | wc -l`
  fi
 done
 if [ $sorted == "yes" ]; then
  cat $TMPFILEsort | awk 'BEGIN { FS = " " } ; { printf ( "%16s\t%12s\n", $1, $2) }' | sort -rgk2 > /tmp/ttt-$TS
  cat /tmp/ttt-$TS > $TMPFILEsort
  rm -f /tmp/ttt-$TS
  cat $TMPFILEsort
 fi
fi

### Remove tmp file
if [ $verbose == "yes" ]; then
 echo ""
 echo "Remove $TMPFILE"
fi
rm -f $TMPFILE
if [ $sorted == "yes" ]; then
 if [ $verbose == "yes" ]; then
  echo "Remove $TMPFILEsort"
 fi
 rm -f $TMPFILEsort
fi


使用方法如下 :
Usage: /Path/to/ana_ipfw.sh [-p] [-i] [-v] [-s] [-o] [-d date_limit]  [filename]
   -p           port analysis
   -i           IP address analysis
   -d           date format
                        +DDAY   from DDAY to today
                        +-DDAY  DDAY days ago
                        YYYYMMDD-YYYYMMDD  from first YYYYMMDD to last YYYYMMDD
                        total   all data records in the log file
   -s           sorted by count
   -o           only data and disable verbose
   -v           enable verbose messages
   filename     default : /var/log/ipfw.log


分析範例如下 :
今天的 port 分析
# ./ana_ipfw.sh -p
[[[ Port Analysis ]]]
 Port Number           Count
------------        --------
          21               4
          22              14
          25              13
          80              30
         111               2
         199               2
         389               2
         443               8
         873               2
        2049               2
        3000              36
        3306              11
        5800               2
        5900               5
        6000               2
        6001               2


今天的 port 分析(按照數量排序)
# ./ana_ipfw.sh -ps
[[[ Port Analysis ]]]
 Port Number           Count
------------        --------
        3000              36
          80              30
          22              14
          25              13
        3306              12
         443               8
        5900               5
          21               4
        6001               2
        6000               2
        5800               2
        2049               2
         873               2
         389               2
         199               2
         111               2


最近三天的 port 分析
# ./ana_ipfw.sh -p -d +3
[[[ Port Analysis ]]]
 Port Number           Count
------------        --------
          21               7
          22              20
          25              41
          80              72
         111               2
         199               2
         389               2
         443              14
         873               2
        2049               2
        3000              72
        3306              57
        5800               2
        5900              12
        5901               3
        6000               7
        6001               2


最近三天的 port 分析(按照數量排序)
# ./ana_ipfw.sh -p -d +3 -s
[[[ Port Analysis ]]]
 Port Number           Count
------------        --------
        3000              72
          80              72
        3306              57
          25              41
          22              20
         443              14
        5900              12
        6000               7
          21               7
        5901               3
        6001               2
        5800               2
        2049               2
         873               2
         389               2
         199               2
         111               2


最後開進工程模式(用來修 script 用, 應該還有 bug.).
# ./ana_ipfw.sh -pv
Parameters
-p -v --
Date no() Port yes IP no Verbose yes Sort no Logfile /var/log/ipfw.log

Create /tmp/ana_ipfw-1347716436

Get log from /var/log/ipfw.log
Sep 15

Count lines in /tmp/ana_ipfw-1347716436
     495 /tmp/ana_ipfw-1347716436

[[[ Port Analysis ]]]
 Port Number           Count
------------        --------
          21               4
          22              14
          25              13
          80              30
         111               2
         199               2
         389               2
         443               8
         873               2
        2049               2
        3000              36
        3306              12
        5800               2
        5900               5
        6000               2
        6001               2

Remove /tmp/ana_ipfw-1347716436

No comments: