On our ejabberd server instance (jabber.cd.chalmers.se / jabber.se) we've been for some time dealing with something that looks like a botnet DDoS attack. The attack was in the beginning abusing the fact that we had no protection against automatically created accounts (in-band registration) by creating thousands of accounts. By disabling in-band registration and enabling the web registration form (with captcha protection enabled - could actually also reenable in-band registration using the newer captcha feature) there were no longer a problem with lots of bogus accounts constantly being created.
After this protection was activated the attacks didn't stop, but still generated wasted CPU cycles and network bandwidth, (every attempt first initiated a TLS session and tried to log in). According to analysis of our logs, the conclusion was that, during one sample time period (1h) around 500 different nodes, mostly originating from within USA, tried to log in once every 10 minutes, which makes it around 3000 attempts per hour, and this was during the times when the attack was in something that (according to network traffic logs) looked like sleep mode (one could see "plateaus" with traffic increasing with over 200% for several hours, then later almost stopping completely, going back to the "normal" 3000 attempts per hour mode).
To minimize the the number of wasted CPU cycles and bits transferred back and forth I decided to add some kind of greylisting, cutting the attacker before establishing TLS sessions and whatnot. To meet these goals I wrote a small ejabberd module, mod_greylist.
The module is fairly stupid - but works fairly well for the scenario described in this email. Since all the attempts were so similar, it was easy to create a regular expression to match against the attempted logins, and when one such failed attempt was triggered, the source IP was added to a greylist, banning it for a number of hours. After running for a while on our server, it built up a greylist of almost 700 IP addresses, killing future connections before they manage to initiate any XML streams or TLS sessions, thus making the impact of the attacks smaller, which was the goal.
Before using, you need to apply to ejabberd two bug fixes:
- ejabberd_c2s crash fix: http://github.com/jadahl/ejabberd/commits/blacklist_hook_bugfix
- and ejabberd_receiver process leak fix: http://github.com/jadahl/ejabberd/commits/ejabberd_receiver_leak_fix
This mod_greylist is available on my github account: http://github.com/jadahl/ejabberd/commits/mod_greylist/2.1.x
Or download the module directly from: http://github.com/jadahl/ejabberd/raw/mod_greylist/2.1.x/src/mod_greylist.erl
The module configuration is described in the first lines in http://github.com/jadahl/ejabberd/raw/mod_greylist/2.1.x/src/mod_greylist.erl