Revision [2788]

This is an old revision of ddosDotSh made by JeffTaylor on 2012-02-18 11:08:51.

 

#!/bin/bash

## ddos.sh - Written by Jeff Taylor (Shdwdrgn)
## Updated 2012-02-17

## 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.

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

## Interface to monitor (optional)
#SRCDEV=wan0
#DSTDEV=eth0

## 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="/root/ddos.block.tmp"

## Name of iptables chain and method for adding new entries
## If you run script from the DNS server, CHAIN="INPUT"
## If you run script from a firewall, CHAIN="FORWARD"
addCHAIN="-I"
CHAIN="INPUT"

## 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 DSTDEV="-i $DSTDEV"; fi
if [ $TIMER -lt 1 ]; then TIMER=225; fi
origIFS=$IFS

dumpCount=35
matches=7
  tcpdump="tcpdump -pnt $DSTDEV $DST udp port 53 -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 }'"


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 $CHAIN | 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" >> $BLOCKFILE
		eval iptables $addCHAIN $CHAIN --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
	  if [ "${timeout:0:1}" != "#" ]; then
		IP=${ip#\#}
		if [ ! "$multi" ]; then multi=1 ; fi
		if [ $timeout -lt $now ] ; then
		  eval iptables -D $CHAIN --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" >> $BLOCKFILE
		  fi
		fi
	  fi
	done < $BLOCKFILE
  fi

  sleep 1
done
There are no comments on this page.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki