Dobrev.EU Blog

Things I want to share

D/DoS Mitigation Using Apache With Mod_evasive

| Comments

Every website as long as becoming popular needs a proper DoS or DDoS protection. There is a plenty of solutions out there but mod_evasive offers something that others don’t – ability to manage upstream firewalls and block traffic directly there as well as serving a Forbidden page.

What is mod_evasive?

According to the official website

mod_evasive is an evasive maneuvers module for Apache to provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack. It is also designed to be a detection and network management tool, and can be easily configured to talk to ipchains, firewalls, routers, and etcetera. mod_evasive presently reports abuses via email and syslog facilities.

Installation

Installation on Debian or Ubuntu
1
apt-get install libapache2-mod-evasive

Enable module

Enable mod_evasive on Debian or Ubuntu
1
a2enmod mod-evasive

Configuration

By default mod_evasive comes without a default configuration. One can use the following example:

mod_evasive sample configuration
1
2
3
4
5
6
7
8
9
10
<IfModule mod_evasive20.c>
  DOSHashTableSize 3097
  DOSPageCount 3
  DOSSiteCount 100
  DOSPageInterval 3
  DOSSiteInterval 5
  DOSBlockingPeriod 600
  DOSLogDir "/var/log/apache2/modevasive/"
  DOSEmailNotify your@email.address
</IfModule>

Block the IP on the Linux firewall too

If you want to block the offending IP on your Linux firewall then add to the configuration the following line

Execute system command in case of DoS
1
DOSSystemCommand "sudo /usr/local/bin/mod_evasive_rule.sh %s"

The script I’m executing is quite simple and adds a rule to an iptables chain.

/usr/local/bin/mod_evasive_rule.sh source
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/bash
#
# mod_evasive_rule.sh
#
# Copyright (C) 2014 - Martin Dobrev
#
# Released under GNU GPLv3
#

# CONFIGURATION

# Get the IP to block
IP2BLOCK="$1"

# Default time to ban in seconds
BAN_TIME=3600

# Webserver username
APACHE_USER="www-data"

# mod_evasive chain
CHAIN_NAME="mod_evasive"

# rule destination
RULE_DEST="reject"

function gc_blocked() {
    BLOCKED_IPS=$( sudo /sbin/iptables -nvxL ${CHAIN_NAME} | grep "Blocked at unixtime" | awk -v ban_time=${BAN_TIME} '{ if ( (systime() - $14) > ban_time ) { print $14" "$8 } }')

    # Return if list empty
    [[ -z "$BLOCKED_IPS" ]] && return

    echo ${BLOCKED_IPS} |

    while read TS IP; do
      sudo /sbin/iptables -D ${CHAIN_NAME} -s $IP -m comment --comment "Blocked at unixtime: $TS" -j ${RULE_DEST}
    done
}

function block_ip() {
    sudo /sbin/iptables -I ${CHAIN_NAME} 1 -s $1 -m comment --comment "Blocked at unixtime: $( date +%s )" -j ${RULE_DEST}
}

# Remove expired bans
gc_blocked

[[ -n "$1" ]] && block_ip $1

exit 0

As you can see the script requires sudo rights in order to manipulate the firewall. On multi-user systems this might introduce a security problem so use on your own discretion.

/etc/sudoers.d/mod_evasive
1
2
3
User_Alias      APACHE = www-data
Cmnd_Alias      FIREWALL = /sbin/iptables, /usr/local/bin/mod_evasive_rule.sh
APACHE          ALL = (ALL) NOPASSWD: FIREWALL

Comments