Saturday, November 29, 2014

Apache: How to Automatically Null Route Abusive Hosts

I notice tons of suspicious requests in my apache log files. I simply don't like this, so if someone or something makes a request for a file that doesn't exist on one of my systems, that earns them a lifetime ban. Here's how we do that. First, modify /etc/httpd/conf/httpd.conf and find this line: DocumentRoot "/var/www/html" Add this, directly after:
RewriteEngine on
RewriteCond %{REQUEST_URI} !/myfile1.html$
RewriteCond %{REQUEST_URI} !/myfile2.html$
RewriteRule ^(.*)$ /block.cgi
Where myfile1.html and myfile2.html are files that actually exist. This will route all other requests to a file called 'block.cgi'. Now, create a file, called: /var/www/html/block.cgi which contains:
# The null router..   There is a redirect in http.conf which executes
# this script by default. Because really, if someone is hitting us
# with a GET request on /, they're up to no good so bye-bye.
# McLovin

use strict;
use CGI qw(:standard);

my $date = `date`;
chomp $date;
my $ip = $ENV{'REMOTE_ADDR'};

open FH, ">> /root/blocked_hosts.txt";
print FH "#$date\n/sbin/route add $ip gw lo\n";
close FH;

print header;
print start_html("Environment");
system "sudo /sbin/route add $ip gw lo"; 
print end_html;
Make sure that file is executable, next, make sure that the apache user can execute that script by adding the following to sudoers:
apache ALL = NOPASSWD: /sbin/route
One final touch, I log each blocked host, so that file needs to be owned by user: apache.
touch /root/blocked_hosts.txt && chown apache:apache /root/blocked_hosts.txt
Now, test that out and make sure it's working. After a failed request, you should see the IP in the output of netstat, like this:
netstat -rn|grep lo$ UGH       0 0          0 lo UGH       0 0          0 lo