I had the same situation last week - a South African hacker pounding at my server with over 2,000 active channels
I found the script below, authored by Ryan on the PBXiaf team, which tests to see if an IP exceeds a pre-determined set of connections on one port (5060 for PBX), and if so, ban the IP.
Hope it helps
Script to block IPs if they have too many accesses on one Port
by ryan
http://rfxn.com/downloads/fguard
#!/bin/sh
email for alerts
email="[email protected]"
path to route command
route_cmd="/sbin/route"
1 = enabled, 0 or 2+ = disabled
route_ban=“0”
port:trigger
ptrig=“80:50 443:50 110:40 25:40 26:40”
white space or comma seperate list too ignore files
the file /root/.fg_ipignore is a static ip ignroe file, line seperated
igfiles="/etc/apf/allow_hosts.rules /etc/apf/deny_hosts.rules /root/.fg_ipignore"
path to iptables firewall script
ipt_cmd="/etc/apf/apf"
path to fguard log
fglog=/var/log/fguard.log
temporary file location for netstat output
ntl=/root/.ntcache
fetch hostname
hname=hostname
unix time for lock tracking
utime=date +"%s"
lock file path
lock="/root/.fg.lock.utime"
lock file timeout in seconds
lock_timeout=“300”
max listings to use from connected hosts
mlist=30
####################################
####################################
eout() {
call arg 1 with value for string to be logged
output=$1
call arg 2 with value 1 for logging too $fglog (eout “text” 1)
logt=$2
if [ ! “$output” == “” ] && [ “$logt” == “” ]; then
echo “$(date +”%b %d %H:%M:%S") fguard($$): $output"
elif [ ! “$output” == “” ] && [ “$logt” == “1” ]; then
echo “$(date +”%b %d %H:%M:%S") $(hostname -s) fguard($$): $output" >> $fglog
fi
}
get_state() {
lock routine to prevent toe-stepping from multiple instances
if [ -f “$lock” ]; then
oval=cat $lock
diff=$[utime-oval]
if [ “$diff” -gt “$lock_timeout” ]; then
echo “$utime” > $lock
eout “cleared stale lock file file” 1
eout "cleared stale lock file file"
else
eout “locked subsystem, already running ? ($lock is $diff seconds old) - aborting” 1
eout "locked subsystem, already running ? ($lock is $diff seconds old) - aborting"
exit 1
fi
else
echo “$utime” > $lock
fi
}
and run the function - die if we are double running
get_state
cleanup files
clfiles() {
rm -f /root/.fg_igtmp
rm -f $ntl
touch /root/.fg_igtmp
chmod 600 /root/.fg_igtmp
if [ ! -f “/root/.fg_ipignore” ]; then
touch /root/.fg_ipignore
chmod 600 /root/.fg_ipignore
fi
if [ ! -f “$ntl” ]; then
touch $ntl
chmod 640 $ntl*
chown root:wheel $ntl*
else
chmod 640 $ntl*
chown root:wheel $ntl*
fi
if [ “$1” == “1” ]; then
rm -f $ntl*
rm -f /root/.fg.lock.utime
fi
if [ ! -f “$fglog” ]; then
touch $fglog
chmod 640 $fglog
chown root:wheel $fglog
else
chmod 640 $fglog
chown root:wheel $fglog
fi
}
clear temp files and create any required
clfiles
loop through the ignore files, strip out #'s and place into a single file
for i in echo $igfiles
; do
cat $i | grep -v “#” >> /root/.fg_igtmp
done
local addresses into ignore file
/sbin/ifconfig | grep inet | cut -d : -f 2 | cut -d \ -f 1 | tr ’ ’ ‘\n’ >> /root/.fg_igtmp
echo “0.0.0.0” >> /root/.fg_igtmp
cat /root/.fg_igtmp | grep -ie ‘[a-z|A-Z|0-9]’ > /root/.fg_igtmp2
mv /root/.fg_igtmp2 /root/.fg_igtmp
nice -n 19 netstat -na | grep tcp | sed ‘s/::ffff://’ | sed ‘s/::ffff://’ > $ntl 2> /dev/null
check status of connections against each port
for chk in echo $ptrig
; do
port=echo $chk | tr ':' ' ' | awk '{print$1}'
trig=echo $chk | tr ':' ' ' | awk '{print$2}'
cat $ntl | grep :$port | awk ‘{print$5}’ | tr ‘:’ ’ ’ | awk ‘{print$1}’ | grep -vwf /root/.fg_igtmp | grep -E ‘[0-9]’ | sort -n | uniq -c | sort -n | tail -n $mlist > $ntl.run
audit amount of connections from each ip agains port
for audit in cat $ntl.run | awk '{print$1"%"$2}'
; do
cnt=echo $audit | tr '%' ' ' | awk '{print$1}'
host=echo $audit | tr '%' ' ' | awk '{print$2}'
if [ ! “$host” == “” ]; then
# if already banned - ignore
banchk=grep -ri $host /etc/apf/deny_hosts.rules
# ban anyone connected above the $trig value for a port
if [ “$banchk” == “” ] && [ “$cnt” -gt “$trig” ]; then
eout “connection flood to port $port banned from $host - $cnt connections” 1
eout “connection flood to port $port banned from $host - $cnt connections”
$ipt_cmd -d $host “fguard ban: $cnt connections to port $port” >> /dev/null 2>&1
if [ “$route_ban” == “1” ]; then
$route_cmd add -host $host reject
fi
# send email alert
echo “fguard monitor on $hname detected a connection based flood from $host connected to port $port with $cnt connections, the attacking host has been banned.” | mail -s “fguard alert from $hname” $email
fi
fi
done
done
cleanup files
clfiles 1