Wiki source for ddosDotSh
Please note the following code has been deprecated in favor of a more robust [[ddosDotPl|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%%
%%#!/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%%