#!/bin/sh
#
# antidos beta 0.6 [antidos@r-fx.org]
###
# Copyright (C) 1999-2004, R-fx Networks <proj@r-fx.org>
# Copyright (C) 2004, Ryan MacDonald <ryan@r-fx.org>
#
#    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
###
#
# Just a global PATH so we can find common binaries
PATH=/sbin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:$PATH

APF_BASE="/etc/apf"
INSTALL_PATH="$APF_BASE/ad"
CNF1="$INSTALL_PATH/conf.antidos"
CNF2="$APF_BASE/conf.apf"
TMPSF="$APF_BASE/.tmpsf"

if [ ! -f $CNF2 ]; then
        echo "could not find $CNF2, aborting."
        exit 1
else
        . $CNF2
fi

if [ ! -f $CNF1 ]; then
	echo "could not find $CNF1, aborting."
	exit 1
else
	. $CNF1
fi


ifconfig=/sbin/ifconfig
ip=/sbin/ip
if [ ! -f "$ip" ] && [ ! -f "$ifconfig" ]; then
	echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): $ip and $ifconfig command not found, aborting." >> $ANTILOG
        exit 1
elif [ -f "$ifconfig" ]; then
	MAD=`$ifconfig $IN_IF | grep inet | cut -d : -f 2 | cut -d \  -f 1`
elif [ -f "$ip" ]; then
	MAD=`$ip addr list | grep -w inet | grep -w eth0 | tac | tail -n 1 | tr '/' ' ' | awk '{print$2}'`
fi

if [ "$MAD" = "" ]; then
        echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): couldnt fetch main adapter address, aborting." >> $ANTILOG
        echo "couldnt fetch main adapter address, aborting."
        exit 1
fi

get_state() {
##
# Lock routine to prevent toe-stepping from multiple instances
##
if [ -f "$LOCK" ]; then
        OVAL=`cat $LOCK`
        DIFF=$[UTIME-OVAL]
        if [ "$DIFF" -gt "$LOCK_TIMEOUT" ]; then
                echo "$UTIME" > $LOCK
                echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): cleared stale lock file file." >> $ANTILOG
        else
                echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): locked subsystem, already running ? ($LOCK is $DIFF seconds old), aborting." >> $ANTILOG
                exit 1
        fi
else
        echo "$UTIME" > $LOCK
fi
}

logf() {
ARG="$1"
if [ ! -f "$ARG" ]; then
	touch $ARG
	chmod 600 $ARG
elif [ -f "$ARG" ] && [ "$2" == "1" ]; then
	rm -f $ARG
        touch $ARG
        chmod 600 $ARG
elif [ ! -f "$ARG" ] && [ "$2" == "2" ]; then
	echo "$ARG not found, aborting."
	exit 1
fi
}

get_mnum() {
CDATE=`date +"%d"`
DATE=`cat $MNUM_F | tr ':' ' ' | awk '{print$1}'`
MNUM=`cat $MNUM_F | tr ':' ' ' | awk '{print$2}'`

if [ ! -z "$CDATE" ] && [ ! -z "$DATE" ] && [ "$CDATE" -gt "$DATE" ]; then
	logf $MNUM_F 1
	MNUM="0"
fi

if [ "$MNUM" == "" ]; then
	MNUM="0"
fi
}

write_mnum() {
DATE=`date +"%d"`
if [ "$MNUM" == "" ]; then
        MNUM="0"
fi

echo "$DATE:$MNUM" > $MNUM_F
}

lcheck() {
LOAD=`cat /proc/loadavg | tr '.' ' ' | awk '{print$1}'`
if [ "$LOAD" -gt "$MLOAD" ]; then
        echo "error load too high to run antidos safely, aborting."
        exit 1
fi
}

pre() {
	logf $ANTILOG 2
	if [ -f "$ANTILOG" ]; then
		ln -fs $ANTILOG $INSTALL_PATH
	fi
	logf $TMPF 1
	logf $TMPF
	logf $TMPSF 1
	logf $TMPSF
	logf $WARIN 2
	if [ "$LP_SLOG" == "1" ]; then
	logf $SLOG 2
	fi
	if [ "$LP_KLOG" == "1" ]; then
	logf $KLOG 2
	fi
	logf $MNUM_F
	get_mnum
	write_mnum

if [ "$DET_SF" == "1" ]; then
SFV=0
if [ "$SF_TY" == "" ]; then
	SF_TY="SYN_RECV"
fi
for i in `echo $SF_TY | tr ',' ' '`; do
	netstat -na | grep $i | awk '{print$4" "$5}' | tr ':' ' ' >> $TMPSF
done

for i in `cat $TMPSF | awk '{print$3}' | grep -wvf $IGNORE`; do
SRC=`echo $i | grep -wvf $IGNORE_HOSTS`
DST=`cat $TMPSF | grep -w $i | awk '{print$1}' | tail -n 1`
DPT=`cat $TMPSF | grep -w $i | awk '{print$2}' | grep -wvf $IGNORE | grep -wvf $IGNORE | tail -n 1`
SPT=`cat $TMPSF | grep -w $i | awk '{print$4}' | grep -wvf $IGNORE | grep -wvf $IGNORE | tail -n 1`
        if [ ! "$PREV" == "$i:$SPT:$DST:$DPT" ]; then
        PREV="$i:$SPT:$DST:$DPT"
        SF_VAL=`cat $TMPSF | grep -w $i | grep -c ""`
	VALBT=`cat $BLOCKR | grep -w $i | grep -w $DST`
        if [ "$SF_VAL" -gt "$SF_TRIG" ] && [ "$VALBT" == "" ]; then
		if [ ! "$SF_TRIG_PORTS" == "" ]; then
			VALTP=`echo $SF_TRIG_PORTS | grep -w $DPT`
			if [ ! "$VALTP" == "" ]; then
	                 # Run the ad function
			 SFV=1
                	 ad
			fi
		elif [ "$SF_TRIG_PORTS" == "" ]; then
                 # Run the ad function
                 SFV=1
                 ad
		fi
        fi
if [ "$NETBLOCK" == "1" ]; then
 if [ "$NETBLOCK_MASK" == "24" ]; then
        SF_VAL=`echo $i | tr '.' ' ' | awk '{print$1"."$2"."$3}'`
 elif [ "$NETBLOCK_MASK" == "16" ]; then
        SF_VAL=`echo $i | tr '.' ' ' | awk '{print$1"."$2}'`
 else
        SF_VAL=`echo $i | tr '.' ' ' | awk '{print$1"."$2"."$3}'`
 fi
fi
	SF_VAL=`cat $TMPSF | grep -w $SF_VAL | grep -c ""`
        VALBT=`cat $BLOCKR | grep -w $i | grep -w $DST`
        if [ "$SF_VAL" -gt "$SF_TRIG" ] && [ "$VALBT" == "" ]; then
                if [ ! "$SF_TRIG_PORTS" == "" ]; then
                        VALTP=`echo $SF_TRIG_PORTS | grep -w $DPT`
                        if [ ! "$VALTP" == "" ]; then
                         # Run the ad function
                         SFV=1
                         ad
                        fi
                elif [ "$SF_TRIG_PORTS" == "" ]; then
                 # Run the ad function
                 SFV=1
                 ad
                fi
        fi
	fi

done
fi

PREV=""

if [ "$LP_KLOG" == "1" ]; then
VAL_LOG=`$INSTALL_PATH/tlog $KLOG .apf-ad.lp1 | grep -wf $FWCHAINS > $TMPF`
for i in `cat $TMPF | tr ' ' '\n' | grep -w SRC | tr '=' ' ' | awk '{print$2}' | grep -wvf $IGNORE`; do
SRC=`echo $i | grep -wvf $IGNORE_HOSTS`
DST=`cat $TMPF | grep -w $i | tr ' ' '\n' | grep -w DST | tr '=' ' ' | awk '{print$2}' | tail -n 1`
DPT=`cat $TMPF | grep -w $i | tr ' ' '\n' | grep -w DPT | tr '=' ' ' | awk '{print$2}' | grep -wvf $IGNORE | tail -n 1`
SPT=`cat $TMPF | grep -w $i | tr ' ' '\n' | grep -w SPT | tr '=' ' ' | awk '{print$2}' | grep -wvf $IGNORE | tail -n 1`
        if [ ! "$PREV" == "$i:$SPT:$DST:$DPT" ]; then
        PREV="$i:$SPT:$DST:$DPT"
        SRC_VAL=`cat $TMPF | grep -w $i | grep -c ""`
        VALBT=`cat $BLOCKR | grep -w $i | grep -w $DST`
        if [ "$SRC_VAL" -gt "$TRIG" ] && [ "$VALBT" == "" ]; then
                 # Run the ad function
                 ad
        fi
if [ "$NETBLOCK" == "1" ]; then
 if [ "$NETBLOCK_MASK" == "24" ]; then
        SRC_VAL=`echo $i | tr '.' ' ' | awk '{print$1"."$2"."$3}'`
 elif [ "$NETBLOCK_MASK" == "16" ]; then
        SRC_VAL=`echo $i | tr '.' ' ' | awk '{print$1"."$2"}'`
 else
        SRC_VAL=`echo $i | tr '.' ' ' | awk '{print$1"."$2"."$3}'`
 fi
        SRC_VAL=`cat $TMPF | tr ' ' '\n' | grep -w SRC | tr '=' ' ' | awk '{print$2}' | grep -w $SRC_VAL | grep -c ""`
        VALBT=`cat $BLOCKR | grep -w $i | grep -w $DST`
        if [ "$SRC_VAL" -gt "$TRIG" ] && [ "$VALBT" == "" ]; then
                 # Run the ad function
                 ad
        fi
fi
     fi
done
fi
PREV=""

if [ "$LP_SNORT" == "1" ]; then
VAL_LOG=`$INSTALL_PATH/tlog $SLOG .apf-ad.lp2 > $TMPF`
for i in `cat $TMPF | awk '{print$4}' | tr ':' ' ' | awk '{print$1}' | grep -wvf $IGNORE`; do
SRC=`echo $i | grep -wvf $IGNORE_HOSTS`
DST=`cat $TMPF | grep -w $i | awk '{print$6}' | tr ':' ' ' | awk '{print$1}' | tail -n 1`
DPT=`cat $TMPF | grep -w $i | awk '{print$6}' | tr ':' ' ' | awk '{print$2}' | grep -wvf $IGNORE | tail -n 1`
SPT=`cat $TMPF | grep -w $i | awk '{print$4}' | tr ':' ' ' | awk '{print$2}' | grep -wvf $IGNORE | tail -n 1`
        if [ ! "$PREV" == "$i:$SPT:$DST:$DPT" ]; then
        PREV="$i:$SPT:$DST:$DPT"
         SRC_VAL=`cat $TMPF | grep -w $i | grep -c ""`
         VALBT=`cat $BLOCKR | grep -w $i | grep -w $DST`
         if [ "$SRC_VAL" -gt "$TRIG" ] && [ "$VALBT" == "" ]; then
                # Run the ad function
                FVAL=`cat $TMPF | grep -w $i | grep -w "$DST:21"`
                if [ ! "$FVAL" == "" ]; then
                 for fchk in `cat $TMPF | grep -w $i | awk '{print$6}' | grep -wv "$DST:21" | tr ':' ' ' | awk '{print$2}'`; do
                        if [ "$fchk" -gt "1023" ]; then
                                SKIP="1"
                        fi
                 done
                fi
                if [ ! "$SKIP" == "1" ]; then
                        ad
                else
                        SKIP="0"
                fi
         fi
if [ "$NETBLOCK" == "1" ]; then
 if [ "$NETBLOCK_MASK" == "24" ]; then
	SRC_VAL=`echo $i | tr '.' ' ' | awk '{print$1"."$2"."$3}'`
 elif [ "$NETBLOCK_MASK" == "16" ]; then 
	SRC_VAL=`echo $i | tr '.' ' ' | awk '{print$1"."$2}'`
 else
        SRC_VAL=`echo $i | tr '.' ' ' | awk '{print$1"."$2"."$3}'`
 fi
fi
	SRC_VAL=`cat $TMPF | awk '{print$4}' | tr ':' ' ' | awk '{print$1}' | grep -w $SRC_VAL | grep -c ""`
        VALBT=`cat $BLOCKR | grep -w $i | grep -w $DST`
        if [ "$SRC_VAL" -gt "$TRIG" ] && [ "$VALBT" == "" ]; then
                # Run the ad function
                FVAL=`cat $TMPF | grep -w $i | grep -w "$DST:21"`
                if [ ! "$FVAL" == "" ]; then
		 for fchk in `cat $TMPF | grep -w $i | awk '{print$6}' | grep -wv "$DST:21" | tr ':' ' ' | awk '{print$2}'`; do
			if [ "$fchk" -gt "1023" ]; then
				SKIP="1"
			fi
		 done
                fi
		if [ ! "$SKIP" == "1" ]; then
			ad
		else
			SKIP="0"
		fi
        fi
        fi
done
fi
}

ad() {
SKIP=0
  if [ "$DST" == "" ]; then
    echo "fatal error finding \$DST"
    SKIP=1
  fi
  if [ "$SRC" == "" ]; then
    echo "fatal error finding \$SRC"
    SKIP=1
  fi
  if [ "$SRC" == "$MAD" ] || [ "$SRC" == "$DST" ]; then
    echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): $SRC:$SPT -> $DST:$DPT" >> $ANTILOG
    echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): attack source is equal to eth0 !? - no action taken, further investigation recommended" >> $ANTILOG
    SKIP=1
  fi
  SRC_VAL=`cat $BLOCKR | grep -w $SRC`
  if [ "$SRC_VAL" == "" ] && [ "$SKIP" == "0" ]; then
    echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): $SRC:$SPT -> $DST:$DPT" >> $ANTILOG
    echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): $SRC -> $DST (DROPPED)" >> $ANTILOG
    if [ "$IPT_BL" == "1" ]; then
	    echo "\$IPT -A INPUT -s $SRC -d $DST -j \$DSTOP" >> $BLOCKR
	    $IPT -I INPUT -s $SRC -d $DST -j $DSTOP
            eout "(insert) deny $SRC to $DST"
    fi
    if [ "$DROP_IF" == "1" ]; then
	DPT_VAL=`cat $NCRIT_PORTS | grep -w $DPT`
	if [ "$DPT_VAL" == "" ]; then
	 if [ "$MAD" == "$DST" ]; then
	   echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): interface $DST = eth0, not unbound." >> $ANTILOG
	 else
           echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): alias interface $DST unbound." >> $ANTILOG
           /sbin/ip addr del $DST/32 dev $IN_IF >> /dev/null 2>&1
	 fi
	fi
    fi
    if [ "$ROUTE_REJ" == "1" ]; then
         if [ ! "$MAD" == "$DST" ]; then
	        route add -host $SRC reject
	 fi
    fi
    if [ "$USR_ALERT" == "1" ] || [ "$ARIN_ALERT" == "1" ]; then
            IPQ=`whois -h $IPW_SRV $SRC | grep -i abuse | grep "@" | awk '{print$2}' | tail -n 1`
            WHOREP="arin.net"
                if [ ! "$(echo $IPQ | grep -w apnic.net)" == "" ]; then
                        IPW_SRV=whois.apnic.net
                        IPQ=`whois -h $IPW_SRV $SRC | grep -i abuse | grep "@" | awk '{print$2}' | tail -n 1`
                        WHOREP="apnic.net"
                elif [ ! "$(echo $IPQ | grep -w ripe.net)" == "" ]; then
                        IPW_SRV=193.0.0.135
                        IPQ=`whois -h $IPW_SRV $SRC | grep -i abuse | grep "@" | awk '{print$2}' | tail -n 1`
                        WHOREP="ripe.net"
                elif [ ! "$(echo $IPQ | grep -w lacnic.net)" == "" ]; then
                        IPW_SRV=whois.lacnic.net
                        IPQ=`whois -h $IPW_SRV $SRC | grep -i abuse | grep "@" | awk '{print$2}' | tail -n 1`
                        WHOREP="lacnic.net"
                fi
    fi
    if [ "$USR_ALERT" == "1" ]; then
          get_mnum
          if [ "$MNUM" -lt "$MAX_MNUM" ]; then
		SRC_LOG=`cat $TMPF | grep $SRC`
                APFAD_LOG=`cat $ANTILOG | grep $DST | grep $SRC`
                . $WUSR | mail -s "$ARTOPIC" "$USR"
          fi
          MNUM=$[MNUM+1]
          write_mnum $MNUM
	  MNUM_ST="1"
    fi
    if [ "$ARIN_ALERT" == "1" ]; then
	    if [ ! "$IPQ" == "" ]; then
		  if [ ! "$MNUM_ST" == "1" ]; then
		  	get_mnum
		  	MNUM=$[MNUM+1]
		  	write_mnum $MNUM
		  else
			get_mnum
		  fi
		  if [ "$MNUM" -lt "$MAX_MNUM" ]; then
		          SRC_LOG=`cat $TMPF | grep $SRC`
		          . $WARIN | mail -s "$ARTOPIC" "$IPQ"
	        	  echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): found $WHOREP contact for $SRC, email sent to $IPQ." >> $ANTILOG
		  else
			  echo "$(date +"%b %d %H:%M:%S") $(hostname -s) antidos($$): found $WHOREP contact, exceeded email limit; nothing sent." >> $ANTILOG
		  fi
	    fi
    fi
  fi
}

case "$1" in
-a)
	get_state
	lcheck
	pre
	rm -f $LOCK
        ;;
*)
        echo "$0 [-a]"
esac
exit 0
