#!/bin/bash 

version="1.0.6"
RTBH="209.54.140.66"
RTBH_KEY="/etc/rtbh.autopilot.id_rsa"
FAILURES=100
LOOPS=1
REMPATLOOPS=10
AUTHPATLOOPS=25
aph=0
AUTOPILOT_HOSTS[((aph++))]="smtp2.mx.ttec.com"
AUTOPILOT_HOSTS[((aph++))]="debian39.ttec.com"
AUTOPILOT_HOSTS[((aph++))]="debian33.ttec.com"
AUTOPILOT_HOSTS[((aph++))]="debian34.ttec.com"
AUTOPILOT_HOSTS[((aph++))]="debian10.ttec.com"
AUTOPILOT_HOSTS[((aph++))]="debian06.ttec.com"

SIGNALS_TO_TRAP="SIGKILL  SIGHUP SIGTRAP SIGINT SIGABRT SIGUSR1 SIGURG SIGTERM SIGILL  SIGQUIT SIGUSR2 SIGWINCH SIGSEGV"

PROGNAME=`basename $0`

#usage funtion: prints prog name and option(s)
usage() {

	echo "Usage: $PROGNAME -p pattern || -P patternfile -f failures [-r remote-pattern-file] [-R remote-loops] [-l loops] [-s sleep] [-b blackholefile] [-c loops-cleanup-after] [-C] [-V] [-q] [-B rtbh-host] [-k ssh-id-file] [-i hostname-id] [-a pattern] [-L loops] [-S source-addr]"
	echo "-p pattern"
	echo "-P patternfile"
	echo "-f fail-count"
	echo "-r remote-pattern-file"
	echo "-R get remote pats every -R loops"
	echo "-t protect ssh commands with timeout"
	echo "-l loops to run in"
	echo "-L every L loops run bad auth patterns"
	echo "-s sleep-time-in-seconds between loops"
	echo "-S source-addr for ssh to RTBH host"
	echo "-b blackholed list file"
	echo "-C cleanup upon exit"
	echo "-c cleanup every -C loops"
	echo "-V Report version number and exit"
	echo "-q Quiet, only errror output"
	echo "-B rtbh-host"
	echo "-k ssh-id-file"
	echo "-i this host hostname-id"
	echo "-a process auth servers for abusive domains"
	exit 60;
}
 
version () {

echo "`basename $0` version: $version"

exit 0

}


#getopts to parse cmd-line params and perform actions
patind=0
SSHBINDADDR=
while getopts a:b:B:c:Cp:k:i:P:r:R:l:L:s:S:tf:Vq opt; do
	case "$opt" in  
	a) BADAUTHPAT="$OPTARG";;
	b) BANFILE="$OPTARG";;
	B) RTBH="$OPTARG";;
	k) RTBH_KEY="$OPTARG";;
	i) AUTOPILOT_HOSTS[0]="$OPTARG";;
	c) CLEANUPLOOPS=`printf "%d" $OPTARG`;;
	C) CLEANUPEXIT="yes";;
	p) PATTERNS[((patind++))]="$OPTARG";;
	P) PATTERNFILE="$OPTARG";;
	r) REMOTEPATFILE="$OPTARG";;
	R) REMOTEPATLOOPS=`printf "%d" $OPTARG`;;
	t) if [[ "`which timeout`" == "" ]]; then
		if [[ "`which timeout3`" != "" ]]; then
			TIMEOUTCMD="timeout3"
		fi
	   else
		TIMEOUTCMD="timeout -k 15 10"
	   fi
		;;
	l) LOOPS=`printf "%d" $OPTARG`;;
	L) AUTHPATLOOPS=`printf "%d" $OPTARG`;;
	s) SLEEPTIME=`printf "%d" $OPTARG` ;;
	S) SSHBINDADDR="-b $OPTARG";;
	f) FAILURES=`printf "%d" $OPTARG` ;;
	V) version ;;
	q) QUIET=" >/dev/null";;
	*) usage;;
	esac;
done


if [ $# -lt "2" ]; then
	usage >&2;
fi

if [[ "$REMOTEPATLOOPS" == "0" ]]; then REMOTEPATLOOPS=1; fi
if [[ "$CLEANUPLOOPS" == "0" ]]; then CLEANUPLOOPS=1; fi

function get_remote_pattern_file() {


	if [[ "${REMOTEPATFILE}" == "" ]]; then
		return 0
	fi

	if [[ "${PATTERNFILE}" == "" ]]; then
		PATTERNFILE=`mktemp -t "$PROGNAME.$$.XXXXXXXXXX"` || PATTERNFILE=""
                if [[ "$PATTERNFILE" && -f "$PATTERNFILE" ]]; then
                        mv ${PATTERNFILE} ${PATTERNFILE}.tmp && PATTERNFILE="${PATTERNFILE}.tmp"
                        PATFILE_IS_TMP=yes
                fi
                if ! [[ "$PATTERNFILE"  && -f "$PATTERNFILE" ]]; then
			echo "Nowhere to put remote ${REMOTEPATFILE}" >&2
			exit 60
		fi
	fi
	scp -Bq -i $RTBH_KEY autopilot@${RTBH}:${REMOTEPATFILE} ${PATTERNFILE}
	if [[ ! -f ${PATTERNFILE} ]]; then
		echo "Could not copy $REMOTEPATFILE to $PATTERNFILE" >&2
		exit 60
	fi
}

if [[ "${PATTERNS}" == "" ]] && [[ "${PATTERNFILE}" == "" ]] && [[ "${REMOTEPATFILE}" == "" ]]; then
	if [[ $(( LOOPS > 0 )) == 0 ]]; then
		echo "No patterns" >&2
		usage >&2
	fi
elif [[ "${PATTERNFILE}" != "" ]] && [[ ! -f "${PATTERNFILE}" ]]; then
	if ! get_remote_pattern_file; then
		echo "Cant read ${PATTERNFILE}" >&2
		usage >&2
	fi
elif ! get_remote_pattern_file; then
	echo "Cant get remote pattern file ${REMOTEPATFILE}" >&2
	usage >&2
fi

for ((i=0;i<${#FAILURES};i++)); do
	DOTS="${DOTS}."
done

function bancleanup(){

	local INPUT
	local locpattern

	if [[ "$1"  != "" ]] &&  [[ -f "$1" ]]; then
		if [[ "${REMOTEPATFILE}" != "" ]]; then
			locpattern="remote ${REMOTEPATFILE}"
		elif [[ "${PATTERNS}" == "" ]]; then
			locpattern="${PATTERNFILE}"
		fi
		grep -Eo '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'  "$1"| sort | uniq |\
		while read INPUT; do
			sed -i "/^${INPUT}$/d" $1
			${TIMEOUTCMD} ssh ${SSHBINDADDR} -n -i $RTBH_KEY autopilot@$RTBH \
			/usr/local/bin/rtbh-quagga-del-route.sh \
			$INPUT/32 from $USER@${AUTOPILOT_HOSTS[0]} \
			dns-query patterns $PATTERNS $locpattern ${QUIET};
		done 
	fi
}


function cleanup_trap(){

	if [[ -f "$BANFILE" ]]; then
		if [[ "${CLEANUPEXIT}" != "" ]]; then
			bancleanup $BANFILE ${QUIET} && unset CLEANUPEXIT
		fi
		if [[ "${BANFILE_IS_TMP}" == "yes" ]]; then
			rm -f $BANFILE && unset BANFILE
		fi
	fi
	if [[ "${PATFILE_IS_TMP}" == "yes" ]] && [[ -f "${PATTERNFILE}" ]]; then
		rm -f  "${PATTERNFILE}" && unset PATTERNFILE PATFILE_IS_TMP
	fi
	trap - ${SIGNALS_TO_TRAP}
	exit
}



if [[ "${BANFILE}" != "" ]]; then

	if  [[ ! -f "${BANFILE}" ]] && ! touch ${BANFILE}; then

		echo "Banfile ${BANFILE} cannot be used" >&2
		exit 60
	fi
fi


if [[ "${CLEANUPLOOPS}" != "" ]] || [[ "${CLEANUPEXIT}" != "" ]]; then
	if [[ "${BANFILE}" == "" ]]; then 
		BANFILE=`mktemp -t "$PROGNAME.$$.XXXXXXXXXX"` || BANFILE=""
		if [[ "$BANFILE" && -f "$BANFILE" ]]; then
			mv ${BANFILE} ${BANFILE}.tmp && BANFILE="${BANFILE}.tmp"
			BANFILE_IS_TMP=yes
		fi
	fi
fi

if [[ "${BANFILE}"  != "" ]] && [[ "${CLEANUPEXIT}" != "" ]]; then
	trap cleanup_trap ${SIGNALS_TO_TRAP}
elif [[ "${BANFILE_IS_TMP}" == "yes" ]] || [[ "${PATFILE_IS_TMP}" == "yes" ]]; then
        trap cleanup_trap ${SIGNALS_TO_TRAP}
fi

function process_authpattern() {

			baddnsqueries-auths "$1" |\
			while read IP DOMAIN REVERSE; do
				if [[ "$IP" == "" ]] ; then
					continue;
				fi
				OUTPUT=`${TIMEOUTCMD} ssh ${SSHBINDADDR} -n -i $RTBH_KEY autopilot@$RTBH \
				/usr/local/bin/rtbh-quagga-screen-add-route.sh \
				$IP/32 from $USER@${AUTOPILOT_HOSTS[0]} \
				bad auth server $REVERSE for domain $DOMAIN pattern  \"\'$1\'\"`; 
				
				if [[ "$BANFILE" != "" ]] && [[ -f $BANFILE ]] &&\
				  (echo $OUTPUT | grep -q "added"); then
					echo $IP >> "$BANFILE"
				fi
				
				if [[ "${QUIET}" == "" ]]; then
					echo "${OUTPUT}"
				fi
			done; 

}

function process_pattern() {
	local INPUT

			baddnsqueries-srcs  "$1" | grep " ${DOTS}" |\
			while read IP NUM; do 
				if [[ "$IP" == "" ]] || [[ "$NUM" == "" ]]; then
					continue;
				fi
				if  [[ $(( NUM < FAILURES)) == 1 ]] ; then 
					continue;
				fi
				OUTPUT=`${TIMEOUTCMD} ssh ${SSHBINDADDR} -n -i $RTBH_KEY autopilot@$RTBH \
				/usr/local/bin/rtbh-quagga-screen-add-route.sh \
				$IP/32 from $USER@${AUTOPILOT_HOSTS[0]} \
				dns-query pattern  \"\'$1\'\"`; 
				
				if [[ "$BANFILE" != "" ]] && [[ -f $BANFILE ]] &&\
				  (echo $OUTPUT | grep -q "added"); then
					echo $IP >> "$BANFILE"
				fi
				
				if [[ "${QUIET}" == "" ]]; then
					echo "${OUTPUT}"
				fi
			done; 

}


if [[ ! -e "$RTBH_KEY" ]]; then
	echo "no rtbh key" >&2
	exit 1
fi

LASTAUTHPAT=0

for ((i=0;i<$LOOPS;i++)); do 

	if [[ "${PATTERNFILE}" != ""  ]]; then
		grep -v '^#' "${PATTERNFILE}" | grep -v '^#' |\
		while read PATTERN; do
			process_pattern "$PATTERN" ${QUIET}
		done
	fi
	for ((j=0;j<patind;j++)); do
		process_pattern "${PATTERNS[((j))]}" ${QUIET}
	done

	if [[ "$BADAUTHPAT" != "" ]]; then
		if [[ $(( LOOPS < 2)) == 1 ]] || [[ $(( i - LASTAUTHPAT > AUTHPATLOOPS)) == 1 ]] ; then
			LASTAUTHPAT=$i
			process_authpattern "${BADAUTHPAT}"
		fi
	fi

	if [[ "$SLEEPTIME" != "" ]]; then
		sleep $SLEEPTIME
	fi

	if [[ "$i" == "0" ]]; then
		continue
	fi

	if [[ "$CLEANUPLOOPS" != "" ]] && [[ $(( i % CLEANUPLOOPS )) == 0 ]]; then
		bancleanup ${BANFILE} ${QUIET}
	fi	
	
	if [[ "$REMOTEPATLOOPS" != "" ]] && [[ $(( i % REMOTEPATLOOPS )) == 0 ]]; then
		get_remote_pattern_file
	fi

done



if [[ "${CLEANUPEXIT}" == "yes" && "$BANFILE" && -f "$BANFILE" ]]; then
	bancleanup $BANFILE ${QUIET}
fi

if [[ "${BANFILE_IS_TMP}" == "yes" ]]; then
	rm -f "${BANFILE}"
fi
