Revision [2787]
This is an old revision of ddosDotSh made by JeffTaylor on 2012-02-17 07:42:34.
#!/bin/bash ## ddos.sh - Written by Jeff Taylor (Shdwdrgn) ## Updated 2012-02-16 ## 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>/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