Denial of service attacks are popular nowadays. The most dangerous are the so-called distributed denial of service attacks, when network activity aimed at shutting the service down, is launched from a vast number of different locations (IPs). To handle that, in most cases one should have an expensive type of network hardware and software; however, there may be simpler solutions. Atlas Tuesday offers an example in Fighting off a DDOS attack on an Apache web server.
The story goes, when it rains it pours! It’s hard enough to keep websites running without hackers trying to break in. An even worse situation is when hackers simply want you off-line. A few days ago I experienced just that… my first DDOS (distributed denial of service) attack against a high-profile website we host.
The attacker original exploited some legacy code to gain access to the web sites administration tool. After thwarting their attack, our web server immediately started to hit “max client connections”. Even after restarting Apache the max client connections were reached within seconds.
We quickly created bad routes for IP addresses associated with the hack attempts; however this did not resolve the problem. Below is the syntax we used to add bad routes.
Route add –host xxx.xxx.xxx.xxx reject
The Apache log files left no clues as to who was connecting so we had to look elsewhere. After some quick searching we found a terrific PHP script which shows which IP’s are connecting to your web server too much. The script was just want we needed. After about a ½ hour of blocking listed IP addresses the problem went away. In all we blocked a little over 100 IP addresses.
If you’re ever in a situation where Apache is clearly being flooded with connections. Run this script! It will save you a ton of time identifying the attacker(s).
<pre class="php" name="code">
– BEGIN SCRIPT –
<?php
## Functions ##
function getIP($line) {
ereg("[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}",$line,$regMatch);
$ip = $regMatch[0];
if($ip) return $ip; else return "false";
}
function processString($string, $size = 18) {
$string = "[ ".$string;
$length = strlen($string);
$toAdd = $size - $length;
for($x = 0; $x < $toAdd; $x++) {
$string = $string." ";
}
$string = $string."]";
return $string;
}
## Code ##
while (true) {
$cmd = "netstat -n | awk '{ print $5 }'";
exec($cmd, $netstatArray);
$ipArray = array();
foreach($netstatArray as $line) {
$ip = getIP($line);
if($ip != "false" && ip != "127.0.0.1") {
if(array_key_exists($ip, $ipArray))
{
$ipArray[$ip]+=1;
}
else // if not, count=1
{
$ipArray[$ip] = 1;
}
}
}
asort($ipArray);
system("clear");
foreach($ipArray as $ip => $count) {
if ($count < 15)
continue;
echo processString($ip);
echo "\t" .processString(gethostbyaddr($ip), 55);
echo "\tTimes Accessed: " .$count ."\n";
}
echo str_repeat("-", 50) ."\n";
exec("top -n 1", $top_str);
preg_match("#load average:(.+)#i", $top_str[0], $match);
echo "Load Average: " .$match[1] ."\n";
echo str_repeat("-", 50) ."\n";
echo 'Showing $count >= 15: (Escape with ctrl+c)' ."\n";
sleep(10);
}
?>
One should also add that even the basic software firewall products, such as free iptables, are capable of thwarting most kidns of simple DoS attempts, by banning addresses temporarily when the rate of connections becomes too high.
For example, this is how SMTP connections can be limited to 1 per second per IP (burstable 10):
iptables -A INPUT -p tcp --dport 25 --syn -m limit --limit 1/s \
--limit-burst 10 -j ACCEPT
iptables -A INPUT -p tcp --dport 25 --syn -j DROP
Protection against DDoS is a hard task, and in most cases it should be handled with proper tools.