Revision [2785]
This is an old revision of ddosDotSh made by JeffTaylor on 2012-02-16 13:26:36.
#!/bin/bash
## ddos.sh - Written by Jeff Taylor (Shdwdrgn)
## Updated 2012-02-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.
## 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 < 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 --list-rules FORWARD | grep "\-s $IP/" )
if [ ! "$marked" ] || [ ! "$rule" ]; then
#echo ${INFO[$i]}
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" =~ ^# ]]; 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>/d$
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