IP Abuse Detection for DreamHost
« Updated robots.txt for WordPressAdvanced HTTP Redirection »
Alot of people have asked me about the best way to block specific IP addresses that are attacking their servers. No easy answer for sure. Here’s what I came up with.
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.
Once the tests have concluded (on my machine it takes maybe 5 minutes) you have the choice to view an automatically generated .htaccess file that you can copy into your real .htaccess file, full of the correct code to Block the bad IP’s. You can tell them bye bye with a 403 Forbidden.

#!/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 "\033]0;$USER@`hostname`: $HOME\007" ;;
esac
}
function ok_continue()
{ echo -en "\n\033[?25l\033[30;42m[ Press any key to continue ]\033[0m\n" ;read -n 1 ans;echo -en "\033[?25h"; }
function test_title()
{ echo -en "\n\n\033[0;32m\n>>>"; echo -e "\033[1;37m $1 \033[0m \n"; echo -e "\n\n[ ${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.\n\n"
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.\n\n"
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 "\033[?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 "\033[0;33m"; echo -e "$ip" >> $REPORT
host=${host/does/!!!POSSIBLE-ABUSE!!!}; (( t++ )); (( h++ )); ips=" $ip$ips" ;;
not) echo -en "\033[0;33m"; echo -e "$ip" >> $REPORT
host=${host/not/!!!POSSIBLE-ABUSE!!!}; (( t++ )); (( h++ )); ips=" $ip$ips" ;;
PTR) echo -en "\033[0;33m"; echo -e "$ip" >> $REPORT
host=${host/PTR/!!!POSSIBLE-ABUSE!!!}; (( t++ )); (( h++ )); ips=" $ip$ips" ;;
.) echo -en "\033[0;33m"; echo -e "$ip" >> $REPORT
host=${host/\./!!!POSSIBLE-ABUSE!!!}; (( t++ )); (( h++ )); ips=" $ip$ips" ;;
esac
echo -en " ${n}\t${ip}\t${host}\033[0m\n"
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 '\033[0;36m'`Please Select a Domain To Test: `echo -e '\033[0m'`"; echo -ne "\033[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-LOOKUP\nOrder Allow,Deny\nAllow 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 "\033[0;31m [ DONE ]\n\n"
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 "\033[0;31m [ DONE ]\n\n"
fi
cd $HOME; exec sh $0 "$YD" "1"
done
}
function show_report(){
clear; title;
PS3="`echo -e '\033[0;36m'`Please select a course of action: `echo -e '\033[0m'`"; echo -ne "\033[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 "\033[1;30m __________________________________________________________________________ "
echo -e "|\033[1;32m ___ __ __ __ \033[1;30m|"
echo -e "|\033[1;32m / _ \_______ ___ ___ _ / // /__ ___ / /_ \033[1;30m|"
echo -e '|\033[1;32m / // / __/ -_) _ `/ ` \/ _ / _ \(_-</ __/ \033[1;30m|'
echo -e "|\033[0;32m /____/_/ \__/\_,_/_/_/_/_//_/\___/___/\__/ \033[1;30m|"
echo -e "| |"
echo -e "| \033[1;37mDREAMHOST IP ABUSE DETECTION SCRIPT VERSION 0.1\033[1;30m |";
echo -e "\033[1;30m __________________________________________________________________________ \033[0m\n\n"
}
# 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 "\033]0;DREAMHOST IP ABUSE DETECTION SCRIPT\007" ;;
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.
« Updated robots.txt for WordPress
Advanced HTTP Redirection »
Tags: bash, DreamHost, ip abuse, shell script
Please consider donating to support active development of the free software and articles here.![]()
The power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect. Tim Berners-Lee
If there are no concurrent access records the script appears to break.
See function error_abuse(){ on line 5 starting with
cat $TMPDI/$YD/logs/e* |grep 'concurrent\ connection\ limit'
If this line is commented out the script will process the next part of the case statement
access|2*) test_title "TOP 50 IP TEST";
If the line is not commented out the script display comments up to that line and aborts.
Apart from that it is a brilliant concept. My site was recently hacked and it has taken a lot of time to track down the IP addresses using other methods.
is it possible to get a similar script for any general servers? normal apache? i think this dreamhost version does not work for centos OS :(
It's very simple - you read the protocol and write the code. -Bill Joy
HTML | DCMI | GRDDL | XOXO | XDMP | XFN | DOM | XML | XHTML 1.1 Strict | CSS 2.1 | W3C | TLDP | WAI | DISA | ICSI | GIAC | SANS RR | GHOST | DEFCON | NIST | DHS CYBER | NIST | .:: Phrack Magazine ::.
↑ TOPExcept where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 License, just credit with a link.
This site is not supported or endorsed by The Apache Software Foundation (ASF). All software and documentation produced by The ASF is licensed. "Apache" is a trademark of The ASF. HTTPD based on NCSA HTTPd
Can i use this script on any host provider? We are with crucialhost