3rd Step in my mechanism are 2 Services, HTTBL and Bot-Trap.de, both of them are Public Blacklists where well known spammers and abusing IP's are listed. I use HTTBL to block out suspicous & harvester active in the past 5 days. If a user is blocked as a false positive he can easy get unlisted and receive a message how to. Bot-Trap.de is more aggresiv because many people can report IPs to block. They blacklist them as long as somebody want a IP unlisted. If you were Catched by the Bot-Trap Script you will not locked out of the page completely you have to solve a Math Captcha e.g. "What is 2*3 ?"  if you succesfully solve this you can use the page without any further questions. The last both Methodes lookup the IP / Useragend of a Visitor in their Database, to avoid looking up each PageImpression I run those checks  only if some kind of POST date is submited to the page. Normal Browsing is still allowed only each Form Submit is checked.

Sounds cool, How to implement this ?

Because I just written this in a "Dirty Hack" manner I did not build a OneClick Addon, you have to implement all of this manually. But compared to my page it worth. Before the changes I had daily 50 - 150 registrations of Fake users which just want to spam the Forum or comments. After the implementation this is absolutely Zero. My Logfiles prooving that the request still there but they are now blocked. Ok, let start step by step: 1) The .htaccess
You can find a small explanation in german in a older Blogpost I made. If you could not understand German this is no big thing you could basicaly copy and paste the htaccess code and put it in you .htaccess file in your Joomla Root. You find the blog article here. Additional to this I suggest to add also well known bad bot's to your .htaccess File. This Script generate a good base for you. Just hit the Submit Button and use the presented result.
2) HTTBL For HTTBL there are several ways of implementing it in Joomla. First of all I suggest you have a look at the HTTBL Webpage for further Information what this actualy is about and how it works. For Joomla 1.5 there is a Plugin from Michiel Bijöand available. You can try this. I prefer the manual method because I can limit the usage of the mod to the POST variables. So If you want to install it by your self I can give you a PHP class which give you some more options. Copy the following code somewhere in your joomlaroot as httbl.php: [sourcecode lang="php"] < ?php // httBL Class by Marco 'solariz' Goetze (www.solariz.de) class httpBL { var $_httpBL_enabled = true; var $_httpBL_APIKEY = 'enter_you_api_key'; var $_httpBL_DNSBL = "dnsbl.httpbl.org"; var $_httpBL_CACHE = 43200; #12h = 43200 var $_httpBL_BLOCK_TYPE = 1; // 0 = Search Engine, 1=suspicious, 2=Harvester, > see below in function judge var $_httpBL_BLOCK_THREAT = 64; // min THREAT to block 0-255 var $_httpBL_BLOCK_DAYS = 5; // IP Last blacklist activity var $_httpBL_WHITELIST = array(''); var $_httpBL_BLACKLIST = array(''); var $_httpBL_LOGFILE = '/www/solariz.de/sol_include/httpBL.log'; var $_httpBL_REPORT = ""; var $_httpBL_RESPONSE = ""; /*********************** * http:BL KLASSE FÜR SLY PROJEKTE (mg) ******* * http BL wird genutzt um Blacklisted Spambot`s von der Seite auszuschließen * das BL Projekt ist online unter: * http://www.projecthoneypot.org * * * API Dokumentation: * http://www.projecthoneypot.org/httpbl_api.php */ function examine() { // Die examine function übernimmt den kompletten prozess von der query // bis zur entscheidung was passiren soll $IP = $_SERVER['REMOTE_ADDR']; if($this->judge($IP) == true) { // Die überprüfte IP wurde als "Böse" eingestuft header("HTTP/1.1 403 Forbidden"); // HTML Human readable Meldung ausgeben -> ?> ERROR 403 - Forbidden
ERROR 403 - Forbidden
The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated.

Why ?

The used IP is listed in one of our Blacklists due to massively abuse of Services. We actively block access from Harvesters, Spam Servers, dictionary attackers, comment Spammers, Bogus IPs. You can do a lookup and check why your IP is locked out exactly at this URL

Help ! Im not a Spammer or Bot

We are sorry for locking you out. A False positive normaly should not happen, please contact us at and copy and paste this Report into the eMail:
< ?=$this->_httpBL_REPORT?>
< ? // Logfile schreiben // Feb 5 15:28:02 if($FP = @fopen($this->_httpBL_LOGFILE,"a")) { $MSG = strftime("%d.%m.%Y %H:%M:%S")."\t".$IP."\t".$this->_httpBL_RESPONSE."\t".$_SERVER['HTTP_HOST'].$_SERVER['REDIRECT_URL']."\n"; fwrite($FP,$MSG); fclose($FP); }#end if die(); }#end if }#end function function judge($IP) { if(in_array($IP,$this->_httpBL_WHITELIST)) return false; elseif(in_array($IP,$this->_httpBL_BLACKLIST)) return true; $query = $this->query($IP); if(is_array($query)) { $this->_httpBL_RESPONSE = implode(".",$query); $this->_httpBL_REPORT .= "IP: $IP "; $this->_httpBL_REPORT .= "RESPONSE: ".$this->_httpBL_RESPONSE." "; $this->_httpBL_REPORT .= "TIME: ".strftime("%c")." "; $this->_httpBL_REPORT .= "HTTP_HOST: ".$_SERVER['HTTP_HOST']." "; $this->_httpBL_REPORT .= "REDIRECT_URL: ".$_SERVER['REDIRECT_URL']." "; $this->_httpBL_REPORT .= "HTTP_USER_AGENT: ".$_SERVER['HTTP_USER_AGENT']." "; // Positive Antwort, Client IP ist also bekannt in der RBL /* [0] => '127' [1] => '1' [2] => '40' [3] => '1' */ /* Ermitteln der Kategorie in die die IP einsortiert wurde * In der Variable $_httpBL_BLOCK_TYPE wird festgelegt ab welchem * Level geblockt werden soll. Niemals 0 blocken ! * Value Meaning * 0 Search Engine (0) * 1 Suspicious (1) * 2 Harvester (2) * 3 Suspicious &amp; Harvester (1+2) * 4 Comment Spammer (4) * 5 Suspicious &amp; Comment Spammer (1+4) * 6 Harvester &amp; Comment Spammer (2+4) * 7 Suspicious &amp; Harvester &amp; Comment Spammer (1+2+4) */ if($query[3] >= $this->_httpBL_BLOCK_TYPE ) { /* Ausweten des THREAT Levels **** * Threat Scores are a rough guide to determine the threat a particular IP address * may pose to your site. Threat Scores should be treated as a rough measure. * Threat Scores range from 0-255, however they follow a logrithmic scale which * makes it extremely unlikely that a threat score over 200 will ever be returned. **** */ if($query[2] >= $this->_httpBL_BLOCK_THREAT ) { /* Auswerten der DAYS flags *** * The second octet represents the number of * days since last activity. In the example above, it has been 3 days * since the last time the queried IP address saw activity on the Project * Honey Pot network. This value ranges from 0 days to 255 days. This * value is useful in helping you assess how "stale" the information * provided by http:BL is and therefore the extent to which you should * rely on it. ***/ if($query[1] < = $this->_httpBL_BLOCK_DAYS ) { return true; }#end else DAYS }#end if THREAT }#end if TYPE }#end if return false; }#end function function query($adrs) { // Reverse IP for DNSBL query $ip = implode ( '.', array_reverse( explode( '.', $adrs ) ) ); $response = gethostbyname( $this->_httpBL_APIKEY.'.'.$ip.'.'.$this->_httpBL_DNSBL ); $response = explode( '.', $response); // If the response is positive, if ( $response[0] == 127 ) { return $response; } else { // Negative Response return false; }#end else }#end func }#end class ?> [/sourcecode] 3) BOT-TRAP.de
Ok this is optional, you need a Account at bot-trap.de only users which give a personal introduction  will get access to the Code and installation setup. But it is very easy, in short words: You receive a PHP file, add your API Key, copy it to your Joomla Root, and require it in the index.php as first call. e.g. require("bot-trap.php"); Webpage: http://www.bot-trap.de/home/
4) The IP related Captcha
Again you need some custom code to put in your joomla root. It is neccesary that your webserver have GD Lib installed and is able to draw PNGs with GD in PHP. If not the script will throw you an error. Ok, copy and paste the following Code and put it in rndpic.php in your joomla root: [sourcecode lang="php"] < ? examine(); // seed with microseconds since last "whole" second srand ((double)microtime()*1234567890); $image_height = 60; $image_width = 120; $font = "verdana.ttf"; $text = trim($_GET['text']); $font_size = 16; $text1 = substr(ip2hex($_SERVER['REMOTE_ADDR']),2,1).$text[1].substr(ip2hex($_SERVER['REMOTE_ADDR']),3,1).$text[3]; header ("Content-type: image/png"); $im = @ImageCreate ($image_width, $image_height) or die ("Kann keinen neuen GD-Bild-Stream erzeugen"); $background_color = ImageColorAllocate ($im, 255, 255, 255); $text_color[1] = ImageColorAllocate ($im, 93, 0, 0); $text_color[2] = ImageColorAllocate ($im, 0, 93, 0); $text_color[3] = ImageColorAllocate ($im, 0, 93, 93); $text_color[4] = ImageColorAllocate ($im, 90, 110, 53); $bg_color[1] = ImageColorAllocate ($im, rand(188,250), rand(188,250), rand(188,250)); $bg_color[2] = ImageColorAllocate ($im, rand(188,250), rand(188,250), rand(188,250)); $font_y = 33; # Irritierungs Linien & Hintergründe imagefilledrectangle ( $im, rand(0,$image_width/2), rand(0,$image_height/2), rand($image_width/2,$image_width), rand($image_height/2,$image_height), $bg_color[1] ); imagefilledellipse ( $im, rand(0,$image_width), rand(0,$image_height), rand(10,100), rand(10,100),$bg_color[2] ); imageline ( $im, 1, rand(1,$image_height), rand(1,100), rand(1,$image_height), $text_color[1] ); imageline ( $im, 1, rand(1,$image_height), rand(1,100), rand(1,$image_height), $text_color[2] ); imageline ( $im, 1, rand(1,$image_height), rand(1,100), rand(1,$image_height), $text_color[3] ); imageline ( $im, 1, rand(1,$image_height), rand(1,100), rand(1,$image_height), $text_color[4] ); imageline ( $im, 1, rand(1,$image_height), rand(1,100), rand(1,$image_height), $text_color[1] ); # Buchtaben zeichnen $A = substr($text1,0,1); $B = substr($text1,1,1); $C = substr($text1,2,1); $D = substr($text1,3,1); $RandColor = rand(1,4); imagettftext($im, $font_size, rand(-10,10), 10, ($font_y+rand(-12,12)), $text_color[$RandColor], $font, $A); $RandColor = rand(1,4); imagettftext($im, $font_size, rand(-20,20), 40, ($font_y+rand(-12,12)), $text_color[$RandColor], $font, $B); $RandColor = rand(1,4); imagettftext($im, $font_size, rand(-20,20), 60, ($font_y+rand(-12,12)), $text_color[$RandColor], $font, $C); $RandColor = rand(1,4); imagettftext($im, $font_size, rand(-10,10), 85, ($font_y+rand(-12,12)), $text_color[$RandColor], $font, $D); # Image erstellen ImagePNG ($im); function ip2hex($ip) { // Normalisiert eine IP-Adresse in 8-Byte-Zeichenkette if (preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $ip, $match)) { for ($i=1; $i<=4; $i++) { $hex .= sprintf("%02X",$match[$i]); } } return $hex; } ?> [/sourcecode] As you might have seen I include the HTTBL Script also in the Captcha Generating script right at the top to exclude unwanted bots also directly from the captcha. So if they do not see it they can not complete it. As I described at the beginning some Pages use external captcha completion so you never know where your captcha is displayed. If you decide not to use HTTBL simply comment out the first 3 lines of code. (Line 2 - 4)
4) The "Hacking" part
I do not know why somebody started to call this "Hacking" let it name "Patching" or "Changing", sounds cleaner ;) First you need to change some things at the index.php in the Joomla root directory. Set the following Code right at the start of the index.php fille (after the " Next we have to implement the Captcha itself in the Registration Form on you page. To do this please open this file: /components/com_user/views/register/tmpl/default.php You should find this Path structure in your Joomla root. The default.php contains the registration Form for the Joomla page, if you use Templates which override this you have to search where it is stored. After the "defined('_JEXEC') or die('Restricted access'); " pattern and before the " After inserting above code search for "" before this you should find a closed table exactly before this close tag enter this HTML code: [sourcecode lang="html"] *
Please enter the 4 letters of the security image below.

< ?php echo JText::_( 'REGISTER_REQUIRED' ); ?> [/sourcecode] You have to change Line 15 fitting you rndpic.php you saved in step #4
I guess basicaly that's it. Ok this mini Howto may be a bit consusing on some parts but I think every advanced webmaster is able to fill the gaps and implement this on his own page. Sure you have to change some stuff but as I said at the beginning, this is no one Click plugin. Have fun.

✉ MG//