The problem with Apache's approach to dealing with multiple clients, is that there's only ever a limited amount of Client processes available. This is usually is around a few hundred on common webservers.
Because of this, it becomes necessary to handle HTTP requests as quickly as possible. As soon as a request is handled, it can go on serving the next. If a client happens to have a slow connection, this can have a direct effect on the scalability of your frontend server.
A common way to fight this, is to put a caching server in front of your webserver, such as Varnish or Squid. These webservers are better suited to deal with many clients. This will allow your Apache server to send back HTTP responses quickly to the reverse proxy, and let the proxy deal with sending back the response to the client.
However, this doesn't deal with slow requests. Generally, these proxy servers will open connections directly to the backend webserver to avoid having to buffer larger request bodies.
Because PHP installations generally use apache 'prefork mpm', the number of possible connections is considerably low. This is also often the case with Fast-CGI based webservers, such as nginx and lighttpd. So if you were to just able to open up a few hundred connections, and drip in the bytes for the request body it would be very easy to take these servers down.
To test this theory, I wrote a simple python script that does exactly this, you can grab it from github. To use it, try something like this:
- python slowdeath.py --threads 200 http://localhost/
In my case my webserver was limited to 150 connections. It took about a second for it to stop serving requests.
Big warning: This tool is for research purposes only. Use at your own risk, and only on servers you own.
To take out a server, simply specify a number of threads higher than the MaxClients or whatever setting your webserver happens to use. Note that I only tested this on a few servers, so results may vary. Side effects include diarrhea, rashes, blackouts and death. Do not use while driving.

So this will take down apache, nginx and lighttpd?
I thought the whole point of fcgi was for internal multiplexing. So if I have 200 open connections to nginx dripping in bytes the only effect it will have on the system is the overhead of storing the state of those connections in memory on the nginx event loop?
I guess I should try for myself =p
Great blog by the way. You are a great inspiration. = )
I'd say, try out. (I haven't).
If you use fastcgi with nginx, you still need to specify the number of PHP processes. I believe the limit would be that number.
And thanks very much btw :)
I assume this is similar to Slowloris?
http://ha.ckers.org/slowloris/
This is not an issue with Nginx, and I'd wager that it's not an issue with Lighttpd either, though I'll freely admit that I haven't used Lighttpd in years
Nginx will actually buffer the request and only send it to PHP once it's complete, it will also buffer the PHP response and send it to the user. So essentially the PHP process is not busy while the client is sending the request and it's not busy while nginx is sending response to client.
I'm constantly amazed at how many people still use Apache by itself, it's absolutely horrible for performance. You can just look at the low orbit ion cannon tool the chans like to use to bring down sites, it's incredibly crude but it works so well because sites using Apache cannot handle any kind of traffic before it craps itself.
Do yourself a favour and use Nginx, we have some very nice people in #nginx on freenode who are usually ready to answer questions and the wiki is not actually half bad. It'll be your best decision this month.
One of the nice parts of nginx is that you can specify a list of php-fcgi backends to handle your requests so you aren't limited to one php-fcgi per nginx instance. The php processes don't even need to be on the same physical machine
JD,
Definitely looks like its the same as slowloris =) Wasn't aware of that tool, looks pretty advanced.
Martin,
Good to nginx doesn't have the issue, I only had the chance to test with apache.
There is an apache module to protect you from this kind of attacks http://en.wikipedia.org/wiki/Mod_qos
yeah it is scary when you think about it :/ fortunately proxies and netscaler seem to do the job but not everyone has that kind of luxury.
ps. its not really fair to put PHP in the title of the article its web server who is at fault here so why blame PHP? ... hehe :)
cheers
art
@Arthur
PHP is just my realm of knowlegde, and I initially suspected the attack would work for every webserver with limited processes. You're absolutely right though.
It sounds like an appropriate name is quickdeath. :)