Progressive IP Blocking

Written by Rossz Vamos-Wentworth

The current version is available here

I got the basic idea for this project from Neil Gunton. His system is based on the older ipchains and does some things differently, but he still deserves the credit for the concept.

System Requirements: Apache 1.3 w/mod_rewrite, MySQL 4.x, Linux 2.4.x w/iptables, Perl 5.x and suid-perl. The report script requires PHP 4.x. It has NOT been tested with mod_perl.

Dealing with hack attempts, evil webbots, and worms has been an ongoing headache. Most of these problems come from dynamic ip addresses, so simply blocking the offender is only a temporary solution since the blocks are obsolete rather quickly. Examining logs and putting blocks in place is time consuming. Remembering to remove blocks on dynamic ip addresses is also a problem. What was needed was an automated solution.

I wrote my blocking code with these assumptions:

  1. Malicious attempts are usually short term.
  2. These attempts usually come from dynamic ip addresses.

With the following goals in mind:

  1. Block exploit attempts with the minimum of bandwidth overhead.
  2. Minimize the impact on innocents when dynamic ip addresses are involved.
  3. Increasingly punish persistent violations.
  4. Be completely automated.

INSTALLATION & CONFIGURATION

Installation is currently a manual process. One day I may write a script to deal with this, but no promises. The installation and configuration process assumes you are logged in as root.

You'll need the perl module IPTables::IPv4. If you have the CPAN module installed and configured, you can painless install the module with:

perl -MCPAN -e 'install IPTables::IPv4'

Extract the contents of archive:

tar xvzf bottrap-latest.tar.gz

Switch to the created directory:

cd bottrap-0.1

Create the MySQL database:

shell> mysql -p
mysql> create database badhosts;
mysql> source badhosts.sql;
mysql> grant select,insert,update on badhosts.badhosts to bottrap@localhost
identified by 'password';
mysql> flush privileges;
mysql> quit

Create the configuration file as /etc/bottrap.conf with these values (be sure to set the password to the value you used when creating the database:

sql_login = bottrap
sql_pw = password
report_hours = 24
minimum_time = 1
clean_days = 30

Set the owner and permissions for the configuration file. This is required if you wish to use the report script botreport.php. If you don't need the report program, you can leave the owner as root. Your actual apache user name may differ.

shell> chown wwwrun.root /etc/bottrap.conf
shell> chmod 660 /etc/bottrap.conf

Create a directory in your apache document root for the trap script, .e.g '/usr/local/httpd/htdocs/no_way' is what I use, and add a simple .htaccess file with the line 'DirectoryIndex bottrap.pl'. This assumes .htaccess files are enabled. If not, you'll need to modify your global apache configuration file:

Copy bottrap.pl script to this directory and make it root-suid (chmod u+s pissoff.pl). Tell apache to execute .pl as perl scripts in that directory, add this to /etc/httpd.conf (your apache config filename may differ):

<Directory "/usr/local/httpd/htdocs/no_way">
  Options ExecCGI
  AddHandler cgi-script .pl
</Directory>

Disallow this directory to bots by adding the line 'Disallow: /keep_out/' to robots.txt under 'User-agent: *'. And a hidden link to one of your popular web pages. You don't want it visible since curious people might clink on the link.

Copy 'buildbottrap.pl' to a restricted directory such as '/root' and make sure it is owned by root and only executable by root. Set up the block removal script as a cron job using 'crontab -e'. The syntax to execute every 10 minutes is

'0,10,20,30,40,50 * * * * /root/buildbottrap.pl'

If you want to block CodeRed, Nimda, and other annoyances, add this mod_rewrite rule to your apache configuration. Be sure you place it before other rules that might cause this rule to be skipped (watch for line wrapping!):

RewriteCond %{REQUEST_METHOD} "^CONNECT .*:25$" [NC,OR]
RewriteCond %{REQUEST_METHOD} "^POST .*formmail.*" [NC,OR]
RewriteCond %{REQUEST_URI} formmail|cmd\.exe|root\.exe|shtml\.exe|default\.ida|/sumthin [NC]
RewriteRule .* /no_way/pissoff.pl [NC,L]

The first line checks for email proxy attempts. Spammers do this when looking for an insecure system to transfer their garabage into. I'm not sure if that line will actually work. The second line traps POST attempts to formmail. Remove this line if you are foolish enough to run formmail. The third line looks for a formmail exploit attempt, Nimda, a frontpage exploit attempt, CodeRed, and some oddity that keeps popping up in my logs. The final line rewrites anything that matches the previous conditions to run our script.

Now reload your apache settings:

/etc/rc.d/apache reload

Or

apachectl graceful

And test it by accessing the blocking script, e.g.:

http://www.yourdomain.com/no_way/pissoff.pl

Immediately after accessing the script, try accessing anything else on the domain. If you are able to access pages, then it didn't work. Check your apache logs. Don't forget to remove yourself from the database and run buildbottrap.pl afterwards to allow yourself access (or wait for the block to expire).

You'll need some kind of initialization if you want the scripts to work properly after rebooting. Add these two lines to one of your boot scripts:

iptables --new blocks
iptables -A INPUT -p tcp --default-port http -j blocks

If you want to use the report program (botreport.php), copy it to your apache document tree. You may want to restrict access to it.

KNOWN BUGS

Not exactly a bug, more of an annoyance. When someone accesses the blocking script, the block happens immediately. Unfortunately, apache is expecting an ACK to indicate the page was received. The apache process will wait around until it times out. Log entries are deferred until it times out and stamps the entry with the time of the timeout, not of the actual access. The default time out for apache is 300 seconds (5 minutes). I changed it to 60 seconds on my server.