
This shell script analyzes a specific domains apache logs, both error and access, and then finds the IP address that hit your server the most. Then it checks for a a reverse DNS for each of the IP addresses, if it doesn't have a reverse DNS, AND it results in a positive to one of the 3 other tests its added to a bad IP list.
#!/bin/sh
# User-contributed script. Not sponsored by DreamHost.
# Script created 2008-01-16 by AskApache (www.askapache.com)
### SHELL OPTIONS
set +o noclobber # allowed to clobber files
set +o noglob # globbing on
set +o xtrace # change to - to enable tracing
set +o verbose # change to - to enable verbose debugging
set -e # abort on first error
# directory where log files, reports, and generated .htaccess files will be saved
TMPDI="$HOME/ip_abuse"
function exitt(){
case $TERM in
xterm*|vt*|ansi|rxvt|gnome*) echo -e " 33]0;$USER@`hostname`: $HOME 07" ;;
esac
}
function ok_continue()
{ echo -en "n 33[?25l 33[30;42m[ Press any key to continue ] 33[0mn" ;read -n 1 ans;echo -en " 33[?25h"; }
function test_title()
{ echo -en "nn 33[0;32mn>>>"; echo -e " 33[1;37m $1 33[0m n"; echo -e "nn[ ${1} ]n" >> $REPORT; }
function error_abuse(){
clear; title
case "$2" in
connlimit|1*) test_title "CONCURRENT CONNECTION TEST"; future=2
echo -e "Shows IP's making more than 20 requests concurrently.nn"
cat $TMPDI/$YD/logs/e* |grep 'concurrent connection limit'|awk -F ']' '{print $3}' |
awk '{print $2}'|sort|uniq -c |sort -nr|sed 's/^ *//'|egrep "[0-9]{2}+ " > $TMPDI/$YD/logs/out.txt ;;
access|2*) test_title "TOP 50 IP TEST"; future=3
echo -e "Displays the top 50 unique IP addresses that access your site."
echo -e "If they don't have a reverse DNS maybe they should be blocked.nn"
cat $TMPDI/$YD/logs/a* |awk '{print $1|"sort|uniq -dc|sort -nr"}' |egrep "[0-9]{3}+ "|
awk '{print $1,$2}' > $TMPDI/$YD/logs/out.txt ;;
internal|3*) test_title "INTERNAL RECURSION TEST"; future="report"
echo -e "Shows the IP's that triggered an Internal Recursion Error,"
echo -e "meaning that their is a looping problem on your server.n"
cat $TMPDI/$YD/logs/e* |grep 'LimitInternalRecursion'|awk -F ']' '{print $3}'|awk '{print $2}' |
sort|uniq -c|sort -nr|sed 's/^ *//'|egrep "[0-9]{2}+ " > $TMPDI/$YD/logs/out.txt ;;
esac
echo -e " 33[?25l";t=0; h=0; cat $TMPDI/$YD/logs/out.txt |
while read a
do
if [ $t -lt 50 ];then
n=`echo "$a"|awk '{print $1}'`; ip=`echo "$a"|awk '{print $2}'`
host=`nice -n 19 host -qQ -s 1 "${ip}" 2>&1|tr 'n' 't'|awk '{print $2}'`;
case "$host" in
does) echo -en " 33[0;33m"; echo -e "$ip" >> $REPORT
host=${host/does/!!!POSSIBLE-ABUSE!!!}; (( t++ )); (( h++ )); ips=" $ip$ips" ;;
not) echo -en " 33[0;33m"; echo -e "$ip" >> $REPORT
host=${host/not/!!!POSSIBLE-ABUSE!!!}; (( t++ )); (( h++ )); ips=" $ip$ips" ;;
PTR) echo -en " 33[0;33m"; echo -e "$ip" >> $REPORT
host=${host/PTR/!!!POSSIBLE-ABUSE!!!}; (( t++ )); (( h++ )); ips=" $ip$ips" ;;
.) echo -en " 33[0;33m"; echo -e "$ip" >> $REPORT
host=${host/./!!!POSSIBLE-ABUSE!!!}; (( t++ )); (( h++ )); ips=" $ip$ips" ;;
esac
echo -en " ${n}t${ip}t${host} 33[0mn"
if [ $h -gt 3 ]; then
echo -e "Deny from$ips" >> $TMPDI/$YD/.htaccess; h=0; ips=" ";
fi
fi
done
[ $h -gt 0 ] && echo -e "Deny from$ips" >> $TMPDI/$YD/.htaccess
ok_continue; exec sh $0 "$1" "$future"
}
function menu(){
PS3="`echo -e ' 33[0;36m'`Please Select a Domain To Test: `echo -e ' 33[0m'`"; echo -ne " 33[0m"
select v
do
YD="$v"
mkdir -p -m 0755 $TMPDI/$YD/reports
mkdir -p -m 0755 $TMPDI/$YD/logs
echo "" > $TMPDI/$YD/logs/out.txt
echo "" > $TMPDI/$YD/.htaccess
echo -e "## IP-ABUSE-LOOKUPnOrder Allow,DenynAllow from All" > $TMPDI/$YD/.htaccess
ELOG="$TMPDI/$YD/logs/error.log"
ALOG="$TMPDI/$YD/logs/access.log"
REPORT=$(echo -en "$TMPDI/$YD/reports/`date +%mx%dx%y`.txt");
echo "" > $REPORT; echo -e "GENERATED REPORT FOR $YD n`date`n" >> $REPORT
clear; title; cd ~/logs/$YD/http
if [ ! -f $ELOG ]; then
test_title "Creating Error log"
`nice -n 19 gunzip -dc e*.gz | split -b 1m -a 4 -d - $TMPDI/$YD/logs/e.`; wait
cp error.log $TMPDI/$YD/logs; echo -e " 33[0;31m [ DONE ]nn"
fi
if [ ! -f $ALOG ]; then
test_title "Creating access log"
`nice -n 19 gunzip -dc a*.gz | split -b 5m -a 4 -d - $TMPDI/$YD/logs/a.`; wait
cp access.log $TMPDI/$YD/logs; echo -e " 33[0;31m [ DONE ]nn"
fi
cd $HOME; exec sh $0 "$YD" "1"
done
}
function show_report(){
clear; title;
PS3="`echo -e ' 33[0;36m'`Please select a course of action: `echo -e ' 33[0m'`"; echo -ne " 33[0m"
select v in "View Report" "View .htaccess" "Quit"
do
case "$v" in
*Report) clear; title; test_title "VIEWING $REPORT"; cat $REPORT ;;
*htaccess) clear; title; test_title "VIEWING $TMPDI/$YD/.htaccess"; cat $TMPDI/$YD/.htaccess ;;
Quit) break;;
esac
done
exit 0
}
function title(){
# pretty sweet!
echo -e " 33[1;30m __________________________________________________________________________ "
echo -e "| 33[1;32m ___ __ __ __ 33[1;30m|"
echo -e "| 33[1;32m / _ _______ ___ ___ _ / // /__ ___ / /_ 33[1;30m|"
echo -e '| 33[1;32m / // / __/ -_) _ `/ ` / _ / _ (_- __/ 33[1;30m|'
echo -e "| 33[0;32m /____/_/ __/_,_/_/_/_/_//_/___/___/__/ 33[1;30m|"
echo -e "| |"
echo -e "| 33[1;37mDREAMHOST IP ABUSE DETECTION SCRIPT VERSION 0.1 33[1;30m |";
echo -e " 33[1;30m __________________________________________________________________________ 33[0mnn"
}
# catch non-kill exit to reset term / ncurses
trap exitt EXIT
# set window title if client is capable
case $TERM in
xterm*|vt*|ansi|rxvt|gnome*) echo -e " 33]0;DREAMHOST IP ABUSE DETECTION SCRIPT 07" ;;
esac
if [ $# -lt 1 ]; then
clear; title; [ -d $TMPDI ] || mkdir -m 755 $TMPDI
cd ~/logs; DOMAINS=( `ls ~/logs/` ); cd $OLDPWD; menu ${DOMAINS[@]}
else
YD="${1}"
mkdir -p -m 0755 $TMPDI/$YD/reports; mkdir -p -m 0755 $TMPDI/$YD/logs
touch $TMPDI/$YD/logs/out.txt;
ELOG="$TMPDI/$YD/logs/error.log"
ALOG="$TMPDI/$YD/logs/access.log"
REPORT=$(echo -en "$TMPDI/$YD/reports/`date +%mx%dx%y`.txt");
if [ "$2" == "report" ]; then
show_report "$1" "$2"
else
error_abuse "$1" "$2"
fi
fi
exit 0
Read more on the DreamHost wiki page: Block IP Abuse.