Revision [2017]

This is an old revision of AutoBlockSH made by JeffTaylor on 2009-07-02 15:28:28.

 

#!/bin/sh
#
# Autoblock 20060120
# /etc/autoblock/autoblock
# Copyright 2006 by Jeff Taylor
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


#------------------------------------------------------------
# Define file locations, etc
#------------------------------------------------------------
ETH=eth0		# Which interface to set iptables rules
LOG=/var/log/filter	# Tail this file for events of interest
TailLines=8		# Lines to track for quickblocks
Quickblock=3		# How many unique IP's request same lookup

GREP=/bin/grep
IPTABLES="/usr/sbin/iptables"
DIR=`dirname $0`
RULES=$DIR/autoblock.rules
BLOCKED=/etc/blocklist
CONFDATE=`ls -l $RULES | cut -b30-45`
# ${#p[@]} will give the count of elements in array p

#------------------------------------------------------------
# Read in the config file
#------------------------------------------------------------
function GetConfig {
  if [ ! -f "$RULES" ]; then
	echo "Config file $RULES not found!"
	exit 1
  fi

  BLOCKS=-1
  while read LINE; do
	LINE=${LINE//%#*}
	CMD=`echo $LINE | cut -d\  -f1`
	VAL=`echo $LINE | cut -d\  -f2-`
	if [ "$LINE" ] && [ "$CMD" ] ; then
	  #VAL=`echo $VAL | sed -e "s/'/\\'/g"`
	  if [ "$VAL" == "{" ]; then
	    let "BLOCKS = $BLOCKS +1"
	    NAME[$BLOCKS]="$CMD"
	  elif [ "$CMD" == "}" ]; then
	    X=""
	  else
	    VAL=`echo $LINE | cut -d= -f2- | sed 's/^\s*//'`
	    case "$CMD" in
	    info)
	      INFO[$BLOCKS]="$VAL" ;;
	    time)
	      TIME[$BLOCKS]="$VAL" ;;
	    match)
	      G0=""
	      until [ "$VAL" == "" ]; do
	        G1=`echo $VAL | cut -d\| -f1`
	        VAL=`echo $VAL | cut -d\| -f2-`
	        if [ "$VAL" == "$G1" ] ; then VAL="" ; fi
	        if [ "$G0" != "" ] ; then G0="$G0 | " ; fi
	        G0="$G0$GREP \"$G1\""
	      done
	      VAL=$G0
	      MATCH[$BLOCKS]="$VAL" ;;
	    source)
	      SOURCE[$BLOCKS]="$VAL" ;;
	    mode)
	      MODE[$BLOCKS]="$VAL" ;;
	    hits)
	      if [ "$VAL" == "" ] ; then VAL=0 ; fi
	      HITS[$BLOCKS]="$VAL" ;;
	    hittime)
	      if [ "$VAL" == "" ] ; then VAL=0 ; fi
	      HITTIME[$BLOCKS]="$VAL" ;;
	    domain)
	      G0=`echo $VAL | cut -d= -f2 | sed 's/^ *//' | cut -d\| -f1`
	      G1=`echo $VAL | cut -d= -f2 | sed 's/^ *//' | cut -d\| -f2`
	      DOMAIN[$BLOCKS]="sed -e \"s/^.*$G0//\" -e \"s/[$G1].*//\"" ;;
	    esac
	  fi
	fi
  done < $RULES
}

function UpdateIP {
  logIP=$1
  criticalHits=$2
  killDate=$3
  hitsDate=$4

  padIP=`echo "$logIP      " | cut -b-15`
  NEWDATE=`date --date +${killDate} +"%b %d %Y %H:%M"`
  HITDATE=`date --date +${hitsDate} +"%b %d %Y %H:%M"`
  TEST=`grep " $logIP " $BLOCKED`
  fwTEST=`$IPTABLES -nL autoblock | grep " $logIP "`

  if [ $criticalHits -le 1 ]; then
	if [ "$TEST" ]; then
	  sed "/ $logIP /d" $BLOCKED > $BLOCKED.tmp
	  mv $BLOCKED.tmp $BLOCKED
	  # logger -t autoblock "Clearing $logIP"
	fi
	echo " $padIP   $NEWDATE" >> $BLOCKED
	if [ ! "$fwTEST" ]; then
	  $IPTABLES -A autoblock -i $ETH -s $logIP -j autoblock_drop > /dev/null 2>&1
	  if [ "$criticalHits" == "-1" ] ; then
	    logger -t autoblock "Quick-Block $logIP until $NEWDATE"
	  else
	    logger -t autoblock "Blocking $logIP until $NEWDATE"
	  fi
	fi
	#SPAM=`grep -m1 $logIP /var/log/mail`
	if [ "$SPAM" ] ; then
	  logger -t autoblock "FOUND SPAMMER MATCH @ $logIP"
	fi
  else
	hitCount=0
	prevHits=""
	if [ "$TEST" ]; then
	  prevHits=`echo "$TEST" | sed 's/[^#]//g'`
	  hitCount=`echo ${#prevHits}`
	  sed "/ $logIP /d" $BLOCKED > $BLOCKED.tmp
	  mv $BLOCKED.tmp $BLOCKED
	fi
	(( hitCount++ ))
	if [ $hitCount -ge $criticalHits ] ; then
	  echo " $padIP   $NEWDATE" >> $BLOCKED
	  if [ ! "$fwTEST" ]; then
	    $IPTABLES -A autoblock -i $ETH -s $logIP -j autoblock_drop > /dev/null 2>&1
	    # logger -t autoblock "Blocking $logIP until $NEWDATE"
	    logger -t autoblock "Blocking $logIP ($hitCount/$criticalHits)($NEWDATE)"
	  fi
	  #SPAM=`grep -m1 $logIP /var/log/mail`
	  if [ "$SPAM" ] ; then
	    logger -t autoblock "FOUND SPAMMER MATCH @ $logIP"
	  fi
	else
	  echo "#$prevHits $padIP   $HITDATE" >> $BLOCKED
	  #logger -t autoblock "Updating $logIP ($hitCount/$criticalHits)($HITDATE)"
	fi
  fi
  return 0
}

GetConfig
if [ "$BLOCKS" == "-1" ]; then
  echo "Nothing defined in autoblock.conf!"
  exit 1
fi

# This code can be uncommented to show what was read from the config file
# for (( x=0; x<=$BLOCKS; x++ )); do
#   echo "${NAME[$x]} -> ${MATCH[$x]}"
# done

#------------------------------------------------------------
# Clean up and read entries from existing list
#------------------------------------------------------------
touch $BLOCKED
$IPTABLES -F
$IPTABLES -F autoblock
$IPTABLES -F autoblock_drop

$IPTABLES -N autoblock 2> /dev/null
$IPTABLES -N autoblock_drop 2> /dev/null
$IPTABLES -A INPUT -j autoblock
# $IPTABLES -A autoblock_drop $LOGLIMIT -j LOG $LOGLEVEL --log-prefix "AutoBlocked: "
$IPTABLES -A autoblock_drop -j DROP

while read IP DATE; do
  IP=`echo $IP | cut -d# -f1`
  if [ "$IP" ]; then
	$IPTABLES -A autoblock -i $ETH -s $IP -j autoblock_drop > /dev/null 2>&1
	#echo "Added $IP to firewall"
  fi
done < $BLOCKED

#------------------------------------------------------------
# Tail the kernel log file and add new entries to block
#------------------------------------------------------------
tail -n 1 -f $LOG | while read LINE; do
  IP=""
  for (( x=0; x<=$BLOCKS; x++ )); do
	CHK=`eval "echo \"$LINE\" | ${MATCH[$x]}"`
	if [ "$CHK" ]; then  ### Log entry matches one of our flags
	  IP=`echo ${LINE#*${SOURCE[$x]}} | cut -d\  -f1`
	  IP=`echo $IP | cut -d\# -f1`
	  if [ ${#IP} -lt 7 ] ; then IP="" ; fi
	  if [ "$IP" ] ; then
	    UpdateIP "$IP" "${HITS[$x]}" "${TIME[$x]}" "${HITTIME[$x]}"
	    if [ "${DOMAIN[$x]}" ] ; then
	      Domain=`eval "echo \"$LINE\" | ${DOMAIN[$x]}"`
	      #logger "$IP: $Domain"
	      ### Check if someone is pulling the same info from multiple locations
	      HitIP="|$IP|"
	      HitNum=1
	      for (( i=$TailLines; i>0; i-- )); do
	        j=$(($i-1))
	        TailIP[$i]=${TailIP[$j]}
	        TailDomain[$i]=${TailDomain[$j]}
	        if [ "$Domain" == "${TailDomain[$i]}" ] && [ "${TailIP[$i]}" ] ; then
	          if [ "`echo $HitIP | grep ${TailIP[$i]}`" == "" ] ; then
	            HitIP="$HitIP${TailIP[$i]}|"
	            HitNum=$(($HitNum+1))
	            # logger -t autoblock $HitIP
	          fi
	        fi
	      done
	      TailIP[1]=$IP
	      TailDomain[1]=$Domain

	      # logger -t autoblock "HitNum=$HitNum"
	      if [ $HitNum -ge $Quickblock ] ; then
	        HitIP=`echo $HitIP | cut -d\| -f2-`
	        xIP=""
	        until [ ${#HitIP} -lt 2 ]; do
	          xIP=`echo $HitIP | cut -d\| -f1`
	          HitIP=`echo $HitIP | cut -d\| -f2-`
	          if [ "$xIP" ] ; then
	            UpdateIP "$xIP" "-1" "${TIME[$x]}" "${TIME[$x]}"
	          fi
	        done
	      fi
	    fi
	    break  # Only want a single hit on anything found in log file
	  fi
	fi
  done

  CHKDATE=`ls -l $RULES | cut -b30-45`
  if [ "$CONFDATE" != "$CHKDATE" ] ; then
	GetConfig
	CONFDATE=$CHKDATE
	logger -t autoblock "$RULES has been updated"
  fi
done
There are no comments on this page.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki