Dos-apf

From brokenpoet.org wiki

A script that works with APF to add IPs to the firewall - only to be run interactively!



wget http://scripts.brokenpoet.org/dos-apf.sh



#!/bin/bash
#
# dos-apf.sh    version 2.0.4
#    Will auto-detect dos attacks and block hosts accordingly via APF.
#
# Usage:
#   Modify 'maxcon' and 'maxbans' before running script.
#   Simply run 'bash dos-apf.sh'
#   Will not work as cron job.
# New in this version
#    New configuration variable: maxbans
#    badips is now an array
#    added several functions to help parse array (addnew, remove, contains)
#    Removes old bans from deny_hosts.rules & Reloads apf


### START CONFIGURATION

## How many connections allowed before we consider this a dos?
maxcon=40

## How many IPs to ban at one time before cycling old bans?
maxbans=600 #  This number is not yet known.  Please adjust.

## How many seconds to delay before checking for more DOS attacks?
delay=3

### END CONFIGURATION


######## DO NOT MODIFY PAST THIS LINE
badips=()
# Should we really run?
if  $UID != 0 ; then  # Are we root?
    echo "$0 must be ran as root."
    exit 1
fi
if  "`which apf`" == "" && "$1" != "--nodeps" ; then  # does apf exist?
    echo "$0 requires apf"
    exit 1
fi
# Array Functions
contains() 
{
    local temp=${badips[@]/$1/}
    if [[ "${badips[@]}" == "${badips[@]/$1/}" ]]; then
        echo "0"
    else
        echo "1"
    fi
}
## Remove element from array.
remove() {
    local temp=$1
    local output
    for each in $(seq 0 $((${#badips[@]} - 1))); do 
    if [[ ${badips[$each]} != $temp ]]; then
        output=( ${output[@]} ${badips[$each]} )
    fi
    done
    badips=( ${output[@]} )
    return
}
# Add new element to array
addnew() { 
   badips=( ${badips[@]} $1 )
   #echo "ADDED $1"
}
# Add apf entries.
echo -en "Parsing deny_hosts.rules: "
if [  -r /etc/apf/deny_hosts.rules ]; then # does ban file exist?
    apfhosts=`cat /etc/apf/deny_hosts.rules | sed -e '/^#/d'`
    for each in $apfhosts;do
        addnew $each
    done
    if [[ ${#badips[@]} -gt $maxbans ]]; then
        echo "" > /etc/apf/deny_hosts.rules
        for each in ${badips[0]:$((${#badips[@]} - maxbans))}; do
                apf -u $each
        done
        badips=( ${badips[@]:$((${#badips[@]} - maxbans))} )
    fi
    echo ${badips[@]}
        
else
    echo -e "Warning:\tdeny_hosts.rules does not exist"
fi
echo "Searching for dos attacks.."
while  "$1" != "-c" ; do
  netstat=`netstat -tn 2> /dev/null | grep ":80" | awk '{print $5}' | sed -e 's/:.*//' | sort | uniq -c | sort -n | awk '{print $1"-"$2}'`
# Find DOS attacks
  for each in $netstat; do 
        connections=${each/-*/}
        ip=${each/*-/}
        if  "$ip" != "" && $connections -gt $maxcon && `contains $ip` == 0 ; then # Too many connections?
             echo "Auto-Detected DOS with $connections connections from $ip"
                ## Too many bans?
                if [[ $((${#badips[@]} + 1)) -gt $maxbans ]]; then
                  apf -u ${badips[0]}
                  badips=( ${badips[@]:1} )
                fi
                # add IP to our list
                addnew $ip
                apf -d $ip Auto-Detected DOS with $connections connections 2> /dev/null
        fi
  done
  if  "$1" != "-c" ; then
        sleep $delay  # Don't put a load the server
  fi
done
Personal tools