Denial of Service (DoS) request floods can exhaust Apache worker capacity and turn a reachable site into slow responses, timeouts, or repeated 403 and 503 errors long before the host fully runs out of CPU or bandwidth. Blocking abusive request bursts close to the web server reduces wasted application work and helps normal traffic keep moving during scans, brute-force attempts, and short-layer HTTP floods.
On Ubuntu and Debian, mod_evasive is a practical first-line module for per-client request-rate blocking. It tracks repeated requests by client address and by requested URI, then temporarily denies further requests once a configured threshold is crossed, with the block decisions visible in the Apache error log and in marker files under DOSLogDir.
Thresholds that are too strict can block asset-heavy pages, health checks, or busy API clients, so tune them against normal traffic before using aggressive values in production. If Apache sits behind a load balancer, reverse proxy, or CDN, make sure it sees the real client address through a trusted mod_remoteip configuration, or the shared proxy address can be blocked instead of the offending client.
Steps to configure mod_evasive for Apache:
- Install the mod_evasive package and ApacheBench utility.
$ sudo apt-get update && sudo apt-get install --assume-yes libapache2-mod-evasive apache2-utils ##### snipped ##### Setting up libapache2-mod-evasive (1.10.1-6build1) ... apache2_invoke: Enable module evasive
apache2-utils provides ab for the verification step, and the package install usually enables evasive automatically on current Ubuntu and Debian builds.
- Confirm the evasive module is enabled after installation.
$ sudo a2query -m evasive evasive (enabled by maintainer script)
If the query reports disabled, run a2enmod evasive before continuing.
- Create a private directory for mod_evasive lock and marker files.
$ sudo install -d -o www-data -g www-data -m 0750 /var/log/mod_evasive
Use a directory that is writable by the Apache runtime user but not by unprivileged shell users.
- Edit /etc/apache2/mods-available/evasive.conf to set request thresholds and the log directory.
<IfModule mod_evasive20.c> DOSHashTableSize 3097 DOSPageCount 2 DOSSiteCount 50 DOSPageInterval 1 DOSSiteInterval 1 DOSBlockingPeriod 10 DOSLogDir "/var/log/mod_evasive" #DOSEmailNotify admin@host.example.net #DOSSystemCommand "su - someuser -c '/sbin/... %s ...'" #DOSWhitelist 127.0.0.1 </IfModule>
Parameter Description Default DOSHashTableSize Hash table size used for tracking clients and requests. 3097 DOSPageCount Requests to the same page or URI within the page interval. 2 DOSSiteCount Total requests for any object from the same client IP within the site interval. 50 DOSPageInterval Interval for the page count threshold. 1 second DOSSiteInterval Interval for the site count threshold. 1 second DOSBlockingPeriod Block duration in seconds after a threshold is exceeded. 10 seconds DOSEmailNotify Email address to receive blacklist alerts. None DOSSystemCommand Command executed when a client is blacklisted. None DOSLogDir Directory used for lock and marker files. None DOSWhitelist Client IP addresses excluded from blocking. None DOSWhitelist can be repeated for multiple trusted sources, and the upstream module also accepts trailing-octet wildcards when needed.
When traffic arrives through a reverse proxy or CDN, configure mod_remoteip with trusted proxy settings first so the rate limits apply to the real client address.
Overly strict thresholds can block legitimate traffic, and DOSSystemCommand firewall automation can lock out users or monitoring if it is misconfigured.
- Test the Apache configuration before reloading it.
$ sudo apache2ctl -t Syntax OK
Related: How to test Apache configuration
- Restart the apache2 service to apply the new mod_evasive settings.
$ sudo systemctl restart apache2
- Confirm the evasive20_module entry appears in the loaded module list.
$ sudo apache2ctl -M 2>/dev/null | grep evasive20 evasive20_module (shared)
- Run a controlled request burst against a local endpoint to confirm blocking starts.
$ ab -n 200 -c 10 http://127.0.0.1/ This is ApacheBench, Version 2.3 <$Revision: 1903618 $> ##### snipped ##### Complete requests: 200 Failed requests: 194 (Connect: 0, Receive: 0, Length: 194, Exceptions: 0) Non-2xx responses: 194
A high count of Non-2xx responses usually means mod_evasive is returning 403 during the block window.
Only run load tests against systems you control and only at a level that does not disrupt real users.
- Review /var/log/apache2/error.log for evasive20 denial entries.
$ sudo grep -E "evasive20|client denied" /var/log/apache2/error.log | tail -n 3 [Wed Apr 08 04:43:59.011209 2026] [evasive20:error] [pid 3903:tid 281473216717088] [client 127.0.0.1:50136] client denied by server configuration: /var/www/html/ [Wed Apr 08 04:43:59.011231 2026] [evasive20:error] [pid 3903:tid 281473191354656] [client 127.0.0.1:50142] client denied by server configuration: /var/www/html/ [Wed Apr 08 04:43:59.011257 2026] [evasive20:error] [pid 3903:tid 281473216717088] [client 127.0.0.1:50152] client denied by server configuration: /var/www/html/
- Check /var/log/mod_evasive for per-client marker files created during the block period.
$ sudo ls -l /var/log/mod_evasive total 4 -rw-r--r-- 1 www-data www-data 5 Apr 8 04:43 dos-127.0.0.1
Blocks expire after DOSBlockingPeriod, so raise the thresholds or whitelist only trusted automation if legitimate traffic is being denied.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
