%%(bash) #!/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 IPs 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 %% ---- CategoryDNSBlockList