#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
SCRIPTNAME=$(basename $0)
# BlacklistDir hier werden Die Protokoll Dateien gespeichert.
BLACKLISTDIR="/var/lock/modsec2iptables"
# Logger einstellungen
LOG="/usr/bin/logger -i -s -t ${SCRIPTNAME} "

# IP Adressen die nicht gebannt werden können
WHITELIST='
127.0.0.1
0.0.0.0
'
# !!!----Ab hier bitte nichts ändern auser Du weist was du tust----!!!
EXIT_SUCCESS=0
EXIT_FAILURE=1
EXIT_ERROR=2
EXIT_BUG=10

DO_BAN=$EXIT_FAILURE
DO_UNBAN=$EXIT_FAILURE
DO_SEARCH=$EXIT_FAILURE
PORT='80,443'
COMMENT='Http DDos'
IPADRESS=

# Schreibt text mittels logger nach syslog
function log ()
{
	local mesg=$1
	if [ -n "$mesg" ]; then
		$(${LOG} ${mesg})
	fi
}

# gibt die Hilfe für banip aus
function help ()
{
	echo -e "Usage: $SCRIPTNAME [[-u]-i IP address][-s[-p] [-S STRING]]"
	echo -e "\t-u			Entfernt die übergebene IP Adresse"
	echo -e "\t-s			Zeigt die aktuell gebannten IP Adressen"
	echo -e "\t-S 123*			Zeigt Einträge die mit 123 beginnen"
	echo -e "\t-p [http|mail|all]	Optional kann hier der Port übergeben werden. [http [DEFAULT]|mail|all]"
	echo -e "\t-?,-h			Diese Hilfe"
	echo -e "\nEXAMPLE:\n$SCRIPTNAME -i IP -s\t\tLiest den Status der gebannten IP aus"
	echo -e "\nEXAMPLE:\n$SCRIPTNAME -i IP\t\tbannt die IP Adresse an den http Ports 80,443"
	echo -e "\nEXAMPLE:\n$SCRIPTNAME -i IP -p mail\tbannt die IP an den Mailserver Ports 25,465,587"
	echo -e "\nEXAMPLE:\n$SCRIPTNAME -i IP -p all\tbannt die IP an den Mailserver und http Ports 80,443,25,465,587"
	echo -e "\nEXAMPLE:\n$SCRIPTNAME -u -i IP\t\tentfernt den bann der IP Adresse"
	echo -e "\nTIPP: Ausgabe von -s oder -S STRING kann mittels \"banip -S 123*|sort -k 5\" nach datum sortiert werden"
	exit $EXIT_SUCCESS
}

# Test an IP address for validity: http://www.linuxjournal.com/content/validating-ip-address-bash-script
# Usage:
#      check_ip IP_ADDRESS
#      if [[ $? -eq 0 ]]; then echo good; else echo bad; fi
#   OR
#      if check_ip IP_ADDRESS; then echo good; else echo bad; fi
#
function check_ip ()
{
	local	ip=$1
	local	stat=$EXIT_SUCCESS

	# String ist leer
	if [ ! -n $ip ]; then
		stat=$EXIT_FAILURE
	fi

	# Whitelist IP Adress
	if [ $stat -eq $EXIT_SUCCESS ]; then
		for white in $WHITELIST; do
			if [ "x${ip}" == "x${white}" ]; then
				stat=$EXIT_FAILURE
				#echo "$white = $ip EXIT_FAILURE = $EXIT_FAILURE"
				break
			fi
		done
	fi

	if [ $stat -eq $EXIT_SUCCESS ]; then
		# stat ist ab hier FAILURE
		stat=$EXIT_FAILURE
		if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
			OIFS=$IFS
			IFS='.'
			ip=($ip)
			IFS=$OIFS
			[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
			stat=$EXIT_SUCCESS
		fi
	fi

	return $stat
}

# prüft ob eine IP auch in iptables steht.
# gibt die Nummer des eintrages zurück
function check_ban ()
{
	local CMD=''
	CMD=$(/sbin/iptables -L -n --line-numbers|/bin/grep "${1}"|/usr/bin/cut -d " " -f1)
	if [ -n "$CMD" ]; then
		return $CMD
	else
		return $EXIT_SUCCESS
	fi
}

# list alle IP Adressen aus dem Verzeichnis BLACKLISTDIR
# Prüft die Eintragsnummer in iptables
# Gibt die Eintragsnummer von iptables und Erstellungsdatum zurück
function status ()
{
	if [ $UID -gt 0 ]; then
		log "$USER kann die Status funktion von $SCRIPTNAME nicht ausführen!"
		exit $EXIT_ERROR
	fi
	local search_ip=$1
	local search='blacklist-*'
	if [ -n "$search_ip" ]; then
		search="blacklist-$search_ip"
	fi
	LOGFILES=$(/usr/bin/find $BLACKLISTDIR -type f -name "$search")
	for i in $LOGFILES; do
		#echo "Dateiname: ${pfadname##*/}" 
		ipadress="${i##*-}"
		check_ban $ipadress
		var=$?
		datum=$(stat -c %z $i)
		#echo "ipadress = \($ipadress\)"
		if [ $var -gt $EXIT_SUCCESS ]; then
			for num in $var; do
				echo -e "${ipadress}\t iptable Nummer\t ${num}\t erstellt\t $datum"
			done
		else
			echo -e "${ipadress}\t wurde nicht in iptables gefunden erstellt\t $datum"
			echo "Entferne $i wegen ungültigem Eintrag"
			$(rm -f $i)
		fi
		#echo ${i##*-}
	done
	exit $EXIT_SUCCESS
}
if [ $# == 0 ] ; then
	help
fi

while getopts "i:S:p:suh" Option; do
case "$Option" in
	i)	check_ip $OPTARG
		if [ $? -eq $EXIT_FAILURE ]; then
			log "IP $OPTARG kann nicht verwendet werden. Diese ist fehlerhaft oder steht in der Whitelist"
			exit $EXIT_ERROR
		else
			IPADRESS=$OPTARG
			DO_BAN=$EXIT_SUCCESS
			#echo "IP $IPADRESS Okay Rückgabe = $?"
		fi
	;;
	p)	if [ "x$OPTARG" == "x" ]; then
			echo "FEHLER: Bei der -p Option muss [http|mail] übergeben werden."
			exit $EXIT_ERROR
		fi
		if [ "x$OPTARG" == "xmail" ]; then
			PORT='25,465,587'
			COMMENT='Botnet Spamer'
		fi
		if [ "x$OPTARG" == "xall" ]; then
			PORT="${PORT},25,465,587"
			COMMENT='Http Mail Spamer'
		fi
	;;
	h)	help
	;;
	u)	DO_UNBAN=$EXIT_SUCCESS
		if [ $UID -gt 0 ]; then
			log "$USER kann keine IP entfernen!"
			exit $EXIT_ERROR
		fi
	;;
	s)	DO_SEARCH=$EXIT_SUCCESS
	;;
	S)	SEARCH_STRING=$OPTARG
		echo "SEARCH_STRING = $SEARCH_STRING"
		DO_SEARCH=$EXIT_SUCCESS
	;;
	*)	help
	;;
esac
done

# Suchanfrage
if [ $DO_SEARCH -eq $EXIT_SUCCESS ]; then
	if [ $DO_BAN -eq $EXIT_SUCCESS ]; then
		status $IPADRESS
	elif [ -n "$SEARCH_STRING" ]; then
		status $SEARCH_STRING
	else
		status
	fi
	exit $EXIT_SUCCESS
fi
# Gebannte Ip austragen
if [ $DO_UNBAN -eq $EXIT_SUCCESS -a $DO_BAN -eq $EXIT_SUCCESS ]; then
	#echo "DO_UNBAN ist an"
	check_ban $IPADRESS
	NUM=$?
	# ist der Rückgabe wert == 0 ERROR
	if [ $NUM -eq $EXIT_SUCCESS ]; then
		log "Die Ip Adresse $IPADRESS ist nicht gebannt!"
		exit $EXIT_ERROR
	fi

	#echo $NUM
	# alle zurückgegeben Einträge löschen
	for i in $NUM; do 
		log "Entferne Eintrag Nummer $i von IP $IPADRESS"
		$(/sbin/iptables -D INPUT ${i})
		# Existiert eine Logdatei?
		if [ -f "${BLACKLISTDIR}/blacklist-${IPADRESS}" ]; then
			$(rm -f "${BLACKLISTDIR}/blacklist-${IPADRESS}")
		fi
	done
	exit $EXIT_SUCCESS

fi

# ip bannen 
if [ $DO_BAN -eq $EXIT_SUCCESS ]; then
	#echo "DO_BAN ist an"
	check_ban $IPADRESS
	NUM=$?
	# ist der Rückgabewert != 0 ERROR
	if [ $NUM -gt $EXIT_SUCCESS ]; then
		log "Die Ip Adresse $IPADRESS ist schon gebannt!"
                exit $EXIT_ERROR
	fi
	# IP Wird gesperrt und Logdatei angelegt
	log "IP ${IPADRESS} wird gesperrt"
	$(/sbin/iptables -A INPUT --jump REJECT -p tcp --reject-with tcp-reset -m comment --comment "${COMMENT}" -m multiport --dport ${PORT} -s ${IPADRESS})
	# Lagdatei anlegen
	$(/usr/bin/touch "${BLACKLISTDIR}/blacklist-${IPADRESS}")
	exit $EXIT_SUCCESS
fi
exit $EXIT_SUCCESS
