Submitted by Bryan on

Last week was a very frustrating time for me. For whatever reason, an unusually number of botnets decided to zero in on my Drupal site and created what I call an unintentional  Denial of Service attack (DOS). The attack was actually from spambots looking looking for script vulnerabilities found mainly in older versions of e107 and WordPress. Since the target of these spambots were non-Drupal pages, my Drupal site responded by delivering an unusually large number of "page not found" and "access denied" error pages. Eventually, these requests from a multitude of IPs were too many for my server to handle and for all intents and purposes the botnet attack caused a distributed denial of service that prevented me and my users from accessing the site.

These type of attacks on Drupal sites are nothing new and have been observed and discussed at great length at Drupal.org. However, my search at Drupal.org as well as Google didn't really find a solution that completely addressed my problem. Trying to prevent a DDoS attack isn't easy to begin with and at first the answers alluded me.

I originally looked at Drupal for the solution to my problems. While I've used Mollom for months, Mollom is designed to fight off comment spam while the bots attacking my sight were looking for script vulnerabilities that didn't exist. So with Mollom being the wrong tool to fight off this kind of attack, I decided to take a look at the Drupal contributed model Bad Behavior. Bad Behavior is a set of PHP scripts which prevents spambots from accessing your site by analyzing their actual HTTP requests and comparing them to profiles from known spambots then blocks such access and logs their attempts. I actually installed an "unofficial" version of the Bad Behavior module which packages the Bad Behavior 2.1 scripts and utilizes services from Project Honey Pot.

As I had already suspected, looking for Drupal to solve this botnet attack wasn't the answer. Pretty much all Bad Behavior did for me was to take the time Drupal was spending delivering "page not found" error pages and use it to deliver "access denied" error pages. My Drupal site is likely safer with the Bad Behavior module installed, but it was the wrong tool to help me reduce the botnets from overtaxing Drupal running on my server. Ideally, you would like to prevent the attacks ever reaching your server by taking a look at such things as the firewall, router, and switches. However, since I didn't have access to the hardware, I decided it was time to look at my Apache configuration.

I host my sites on a VPS and use cPanel to help manage the site. While cPanel's defaults will give you a stable server there is definitely room to improve the default configuration. Despite all the places I searched for answers, the Apache documentation itself was the most helpful in helping me find which Apache HTTP Server configuration settings I should look when addressing DoS attacks.

I eventually looked at two directives to help resolve my DoS attacks, MaxClients and TimeOut. For whatever reason, cPanel chooses a default value of 150 for MaxClients even though Apache's default is actually 256. Knowing that whenever the MaxClients were reached, my server wasn't accessible to the client, this was the first httpd directive I wanted to change. Raising this number seemed to delay the effects of the botnet overwhelming my server but it didn't quite solve the problem. Now instead of 150 bot requests being capable of stalling out my server, I could process 256 bot requests. All MaxClients did was invite more disrespectful people to a party that was already getting out of hand.

So I moved on to what was ultimately the solution in my case, I lowered the value given in the Timeout directive. The value configured for the Timeout directive is the amount of time the server will wait for certain events before failing a request. Apache gives the following security tips for how this can be configured to help prevent DoS attacks:

The TimeOut directive should be lowered on sites that are subject to DoS attacks. Setting this to as low as a few seconds may be appropriate. As TimeOut is currently used for several different operations, setting it to a low value introduces problems with long running CGI scripts.

For whatever reason, this directive by default is set for 300 seconds. While I can see a number of reasons why you might need five minutes to run a process before failing the request, that's a value I would be more comfortable to have on an intranet server (fully protected by firewall from the wild wild Web) than on an Internet server. So I lowered the TimeOut directive from 300 seconds to 10 seconds. After the value change, the average requests being processed at any given time dropped from 256 down to around 40.  Most Drupal sites are going to need more processing time than 10 seconds, so you'll find out as I did that this number needs to be higher than 10. So far, I have found a value of 45 for the TimeOut directives allows my site to keep server performance high while handling all those requests from the bots without killing legitimate Drupal related processes.

So in the end, if you find that the spambots are overwhelming your Drupal site and you have the ability to override the httpd configuration file, try lowering the value of your Timeout directive down to 45 or some other low number. Doing this first might just solve your your problem and prevent the need for you to write a long winded blog post about your experience.

CMS Topics: 

Comments

How about using fail2ban?

Bo Kleve's picture

Fail2ban (www.fail2ban.org) is good to use if you can control the firewall on your server.

I made myself a filter to block a client connecting and requesting pages that I don't have and some that I have, but that are not publicly available. One requests for one of these pages/programs and they get firewall-ed for 30 minutes.

It's not at the moment a problem with capacity, but more that I don't want to see the requests in the daily logs. And it does give some satisfaction that I have slowed the attackers down.

/BoK

Fail2ban is good when you can

Bo Kleve's picture

Fail2ban is good when you can get the ip-address of an attacker and count the number of times the attack is done over a period of time and on that information decide that you want to slam the door in their face.

For apache it reads the log-files and acts based on that. I have copied the apache-badbots filter that comes with the installation and modified it to handle bad requests and update it when there is a new weekness they try to scan for. Yesterday they scanned for "/adxmlrpc.php", so that is now blocked.

As long as you can find a pattern to trigger on, you can use that to decide when it's time to stop talking to an attacker.

Tell me if you want me to post my filter here.

/BoK

MaxClient

Nicholas Thompson's picture

I wouldn't put that value that high... That's the number of threads that can get spawned.

These threads grown in size as they cache scripts until they get flushed (There is an apache directive to determine how many hits a thread serves before its killed).

On some severs these can be around 20Mb. Therefore, 300 threads will use 6Gb RAM (20 * 300 = 6000Mb). I doubt your VPS has that much RAM.

This makes your problem worse because, instead of Apache turning around and issuing small "I'm too busy" errors, your OS will initially start swapping stuff out of RAM on onto the HD (which slows things down making the problem worse) and then it'll just run out of memory all-together and freeze up.

At least if Apache is rejecting connections, the server ITSELF shouldn't go down.

I experienced a similar problem a while ago and wrote an article about what happens to Apache when you have too many visitors.

Talking about MaxClients

Anonymous's picture

Looking at your article from the link you posted, are you talking about not setting MaxClients too high? In this particular case, you're saying the Cpanel default of 150 is better than the 256 value in the Apache default?

For a DDOS, unless there is a

Anonymous's picture

For a DDOS, unless there is a pattern to the attack it will be just about impossible to stop.

I've been there many times with large adult sites. The only thing I could do was ignore icmp, turn off ip cookies, get the server to use as few resources as possible (changed to nginx), load balance more servers and manually watch the logs to notice some sort of pattern to start dropping packets to ip's.

DDOS management is an exercise in heuristics.

Dale Dude

Solution that works on a P3 with 512MB RAM

nanocaiordo's picture

Hi guys,

our small and already busy server reached a load of 180+ and I was amazed when I was finally able to ssh into it.

A quick search in to my knowledge came back with a huge question mark but a couple of single malt scotch whisky gave me the idea.

It's a small and effective cron script that work perfectly for our needs.
If you want to use it on shared servers it requires adjustments that I'm sure you will know how to handle.

Basically it will scan websites logs for specific UA posting to a specified URI, set iptables or apf to block those ips and rotates the log.

You now know how it woks but you may contact me any time for a copy of the script.

Bad Behavior for Drupal

Michael Hampton's picture

Hey, I ran across this while searching for something else entirely, but I thought I'd drop a note.

Bad Behavior for Drupal is in kind of a bad place right now. Most Bad Behavior ports (e.g. WordPress, Joomla, MediaWiki) execute Bad Behavior very early in the load process, cutting out nearly all the processing time wasted on requests like these. The Drupal module appears to be an unfortunate exception. So, while it does its job of stopping spammers properly, all of Drupal still gets loaded, so you don't really get the intended benefit of cutting down the site resource usage.

For the next major release Bad Behavior is getting a ground-up redesign, which will cause all the platform modules to need to be rewritten. So I'm hoping to be able to address this issue at that time.

A couple of other options I didn't see mentioned are two Apache modules: mod_evasive, which is designed specifically to repel DDoS attacks, and mod_security, which does general ruleset-based blocking (and takes for freaking ever to set up).

Drupal Module Updated

G J Piper's picture

I've recently became a co-maintainer of the Drupal Bad Behavior module. I (hopefully) have ironed out a few of its issues and have it working pretty well. I've added a lot of features and support as well. Try the new 6.x-2.x-dev version found here.

See the full commit log here.

I'm open to any specific suggestions for further improvements you might give me.