Please note the following code has been deprecated in favor of a more robust Perl script.

#!/bin/bash

## ddos.sh - Written by Jeff Taylor (Shdwdrgn)
## Updated 2012-03-15

## To use this script, you must have iptables and tcpdump installed.
## awk, sed, and logger need to be in the path of the user running this script.

## This script is intended to be run by root. Attempts to run under sudo
## have not always been successful and cannot be guarenteed.

## Destination IP (address of your DNS server)(optional)
#DST=10.0.0.211

## Destination interfaces to monitor (required)
DSTDEV=eth0

## Source interfaces to monitor (optional)
#SRCDEV=wan0

## A string to identify this program's actions in syslog
NAME="DNS_Filter"

## Where to store the block file (full path required)
BLOCKFILE="/root/ddos.block"

## Where to store the temp file (full path required)
TEMPFILE="${BLOCKFILE}.tmp"

## Time (in seconds) to keep an IP address blocked (Default is 225)
TIMER=225


##----- Do not edit beyond this point -----##

if [ "$(pidof -xo $$ $(basename $0))" ]; then exit 1 ; fi
if [ ! -f "$BLOCKFILE" ]; then
  echo "#Expires        #IP Address     #Port   #Multiplier" > $BLOCKFILE
fi

if [ "$DST" ]; then DST="dst $DST and"; fi
if [ "$SRCDEV" ]; then SRCDEV="-i $SRCDEV"; fi
if [ "$DSTDEV" ]; then
  DSTMask=$( ifconfig $DSTDEV | grep "inet addr:" | awk '{split($3,ip,":"); split($4,mask,":"); split(ip[2],ip,"."); split(mask[2],mask,"."); bits=8; for(x=255; x>=0; x-=2^i++) map[x]=bits--; for(i=1; i<=4;i++) { subnet+=map[mask[i]]; ip[i]==mask[5-i]?cidr=cidr".0":cidr=cidr"."ip[i]; } print substr(cidr,2)"/"subnet }' )
  DSTMask="not src net ${DSTMask} and"
  DSTDEV="-i $DSTDEV"
fi
if [ $TIMER -lt 1 ]; then TIMER=225; fi
origIFS=$IFS

dumpCount=50
matches=7
  #echo "tcpdump -pnt $DSTDEV $DST $DSTMask udp port 53 and '(ip[2:2] != 0)' -c$dumpCount"
  tcpdump="tcpdump -pnt $DSTDEV $DST $DSTMask udp port 53 and '(ip[2:2] != 0)' -c$dumpCount 2>/dev/null"
  tcpdump="$tcpdump | awk '{"
  tcpdump="$tcpdump n=split(\$2,ip,\".\");"
  tcpdump="$tcpdump if (n<3) split(ip[1],ipv6,\":\");"
  tcpdump="$tcpdump if (ip[1]!=10) {"
  tcpdump="$tcpdump if (n>2) printf \"%s.%s.%s.%s %s \",ip[1],ip[2],ip[3],ip[4],ip[5];"
  tcpdump="$tcpdump else printf \"%s %s \",ip[1],ip[2];"
  tcpdump="$tcpdump if(\$6!=\"[1au]\") printf \"%s \",\$6;"
  tcpdump="$tcpdump print \$7,\$8,\$9"
  tcpdump="$tcpdump } }'"
  tcpdump="$tcpdump | sort | uniq -c"
  tcpdump="$tcpdump | awk '{ if (\$1>=$matches) print \$0 }'"

scriptdir=$(pwd) ; scriptname=$(basename $0) ; self="$scriptdir/$scriptname"
scriptDate=$( stat -c %Y $self )

while true ; do
  IFS=$'\n'
  unset PKT
  unset cPKT
  INFO=( $( eval $tcpdump ) )

  ## If any particular packets exceed our threshold, block that IP address
  now=$( date "+%s" )
  num=${#INFO[@]}
  for (( i=0; i<$num; i++ )); do
	IP=$( echo ${INFO[$i]} | awk '{ print $2 }' )
	PORT=$( echo ${INFO[$i]} | awk '{ print $3 }' )
	URL=$( echo ${INFO[$i]} | awk '{ print $5 }' )

	multi=1
	marked=$( grep "[[:space:]]$IP" $BLOCKFILE )
	rule=$( iptables -nL INPUT | grep "\-s $IP/" )
	if [ ! "$marked" ] || [ ! "$rule" ]; then

	  if [ $PORT -gt 1023 ]; then
		last=$( grep \#$IP $BLOCKFILE )
		if [ "$last" ]; then
		  multi=$( echo $last | awk '{ print $4 }' )
		  if [ ! "$multi" ]; then multi=1 ; fi
		  multi=$(( $multi * 2 ))
		  sed "/\#$IP/d" $BLOCKFILE > $TEMPFILE
		  mv -f $TEMPFILE $BLOCKFILE
		fi
		END=$(( $now + ( $TIMER * $multi )))
		echo "$END      $IP     $PORT   $multi          `date \"+(%x %T)\" -d @$END`" >> $BLOCKFILE
		eval iptables -I INPUT --source $IP $SRCDEV -p udp --sport $PORT -j DROP
		eval iptables -I FORWARD --source $IP $SRCDEV -p udp --sport $PORT -j DROP
		logger -t $NAME \(x$multi\) $IP:$PORT @ $URL
		#logger -t $NAME -- iptables $addCHAIN $CHAIN --source $IP $SRCDEV -p udp --sport $PORT -j DROP
	  fi
	fi
  done


  ## Check if an IPs timer has expired, and remove the block
  IFS=$origIFS
  if [ -f "$BLOCKFILE" ] ; then
	while read timeout ip PORT multi ; do
	  multi=$( echo $multi | sed 's/\s.*//' )
	  if [ "${timeout:0:1}" != "#" ]; then
		IP=${ip#\#}
		if [ ! "$multi" ]; then multi=1 ; fi
		if [ $timeout -lt $now ] ; then
		  eval iptables -D INPUT --source $IP $SRCDEV -p udp --sport $PORT -j DROP 2>/dev/null
		  eval iptables -D FORWARD --source $IP $SRCDEV -p udp --sport $PORT -j DROP 2>/dev/null
		  sed "/$IP/d" $BLOCKFILE > $TEMPFILE
		  mv -f $TEMPFILE $BLOCKFILE

		  if [ "$ip" == "$IP" ]; then
			logger -t $NAME Removed $IP
			END=$(( $now + ( $TIMER * $multi )))
			echo "$END  #$IP    $PORT   $multi          `date \"+(%x %T)\" -d @$END`" >> $BLOCKFILE
		  fi
		fi
	  fi
	done < $BLOCKFILE
  fi

  sleep 1

  ## Check if script has changed
  if [ $scriptDate != $( stat -c %Y $self ) ]; then
	logger -t $NAME Restarting $scriptname
	$self "$@" &
	exit 0
  fi
done
There are no comments on this page.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki