Bringing a more consistent and up-to-date response on the subject, though, without ruling out everything @raonibs said, currently mod_security is enough to protect you from attacks Of and Brute force. Then you can save on one more module and get rid of mod_evasive, which today is an outdated module.
Ratelimit and Dos Protection
After many tests, monitoring and studies, I created the rule below, the operation is simple, first limits access 1 per second when access passes 1000 connections in the minute (this is a high value to avoid false/positive, but you can edit according to your infrastructure), sends the error 429 and Retry-After
to alert search bots and inform to try again after 10 seconds. If Dos attack continues, drop the connection for 60 seconds.
In short, this code is a ratelimit with DOS protection.
It works very well, has been tested with the best known stress tools. But it has no effect on Ddos attacks, and may have a negative effect on some cases of large-scale attacks (but this is a subject for another topic).
# Ratelimit - DoS Protection
SecAction initcol:ip=%{REMOTE_ADDR},pass,nolog,id:'5000750'
# conta requisições por segundo por ip
SecAction "phase:5,id:'5000751',deprecatevar:ip.rlimit=1/1,pass,nolog"
# ignora requisição de localhost ou algum outro ip
SecRule REMOTE_ADDR "^123\.45\.67\.89$" "phase:1,id:'5000740',nolog,allow"
# se as requisições passarem de 100 (var dos>100), derruba a conexão (útil se você usa algum proxy, tipo cloudflare)
SecRule ip:dos "@gt 100" "phase:2,id:'5000752',pause:300,drop,setenv:RATELIMITED,skip:2,log,msg:'IP address blocked - DoS Attack'"
# se as requisições passarem de 1000 (var rlimit>1000), nega a conexão e retorna http 429, e aumenta a var dos em um (expira em 60 segundos)
SecRule ip:rlimit "@gt 1000" "phase:2,id:'5000753',pause:300,deny,setvar:ip.dos=+1,expirevar:ip.dos=60,status:429,setenv:RATELIMITED,skip:1,nolog"
# aumenta a var rlimit em um (expira em 30 segundos)
SecAction "phase:2,id:'5000754',pass,setvar:ip.rlimit=+1,expirevar:ip.rlimit=30,nolog"
Header always set Retry-After "30" env=RATELIMITED
ErrorDocument 429 "Too Many Requests. Calm down!"
Brute Force
Below is an example of rule for protection against Brute force in Wordpress, there are many examples spread over the internet, I made some modifications to this code to work in the latest versions of mod_security and several tests, including with the famous tool Wpscan. Also works very well.
<Locationmatch "/wp-login.php">
# Setup brute force detection.
# React if block flag has been set.
SecRule user:bf_block "@gt 0" "deny,status:401,log,id:5000135,msg:'ip address blocked for 5 minutes, more than 15 login attempts in 3 minutes.'"
# Setup Tracking. On a successful login, a 302 redirect is performed, a 200 indicates login failed.
SecRule RESPONSE_STATUS "^302" "phase:5,t:none,nolog,pass,setvar:ip.bf_counter=0,id:5000136"
SecRule RESPONSE_STATUS "^200" "phase:5,chain,t:none,nolog,pass,setvar:ip.bf_counter=+1,deprecatevar:ip.bf_counter=1/180,id:5000137"
SecRule ip:bf_counter "@gt 15" "t:none,setvar:user.bf_block=1,expirevar:user.bf_block=300,setvar:ip.bf_counter=0"
</locationmatch>
You can change /wp-login.php
for any page you want to protect.
SYN Flood
I also created a protection against SYN Flood and Dos for apache using iptables, compatible with WHM and especially for those who use CSF.
#!/bin/sh
/sbin/iptables -N BLOCK_IP
/sbin/iptables -N SYN_CHECK
/sbin/iptables -N DOS_CHECK
/sbin/iptables -N SYN_ATTACK
/sbin/iptables -N DOS_ATTACK
#
# primeiro verifica se o IP esta bloqueado
/sbin/iptables -A INPUT -j BLOCK_IP
# derruba se estiver bloqueado
/sbin/iptables -A BLOCK_IP -p tcp -m multiport --dport 80,443 -m recent --name BlockedIP --rcheck --seconds 30 -j DROP
/sbin/iptables -A BLOCK_IP -p udp -m multiport --dport 80,443 -m recent --name BlockedIP --rcheck --seconds 30 -j DROP
# se passou o tempo desbloqueia
/sbin/iptables -A BLOCK_IP -p tcp -m multiport --dport 80,443 -m recent --name BlockedIP --remove -j RETURN
/sbin/iptables -A BLOCK_IP -p udp -m multiport --dport 80,443 -m recent --name BlockedIP --remove -j RETURN
#
# verifica: se existe mais de 100 conexões simultâneas com status SYN - ignora IP do gateway
/sbin/iptables -A INPUT -p tcp -m multiport --dport 80,443 --syn ! -s 123.45.67.89 -m connlimit --connlimit-above 100 -j SYN_CHECK
# verifica: conexão feita e posteriormente a frequencia - ignora IP do gateway
/sbin/iptables -A INPUT -p tcp -m multiport --dport 80,443 ! -s 123.45.67.89 -m state --state NEW -j DOS_CHECK
/sbin/iptables -A INPUT -p udp -m multiport --dport 80,443 ! -s 123.45.67.89 -m state --state NEW -j DOS_CHECK
#
# verifica se o ataque é frequente (no caso de erro: --hitcount não pode ser maior que 100 - aumente o limite de pacotes em ip_pkt_list_tot.conf)
/sbin/iptables -A SYN_CHECK -m recent --update --seconds 1 --hitcount 70 --name RATE -j SYN_ATTACK
/sbin/iptables -A DOS_CHECK -m recent --update --seconds 1 --hitcount 70 --name RATE -j DOS_ATTACK
# caso o ataque seja frequente, bloqueia por 30 segundos e gera log
/sbin/iptables -A SYN_ATTACK -j LOG --log-prefix "BLOCK SYN ATTACK: " --log-level 6
/sbin/iptables -A SYN_ATTACK -m recent --set --name BlockedIP -j DROP
/sbin/iptables -A DOS_ATTACK -j LOG --log-prefix "BLOCK DOS ATTACK: " --log-level 6
/sbin/iptables -A DOS_ATTACK -m recent --set --name BlockedIP -j DROP
#
# se o ataque não é frequente, libera
/sbin/iptables -A SYN_CHECK -m recent --set --name RATE -j ACCEPT
/sbin/iptables -A DOS_CHECK -m recent --set --name RATE -j ACCEPT
#
Many people use the fail2ban to protect against SYN Flood, however, not always using fail2ban is something simple, especially for those who already use CSF. This script has been tested and until the date of this post, it works very well. It works to complement the SYN cookies, which must be enabled on your operating system.
To run is very simple, just add the code in the rules of your iptables /etc/sysconfig/iptables
, or if you use CSF just put in /usr/local/csf/bin/csfpre.sh
and type in the terminal csf -r
.
Anti-slowloris
To protect Apache against Slow From attacks, you must use the mod_reqtimeout plugin, I use the configuration below, 10 seconds with 1 second plus every 500 bytes waiting for a connection is sufficient in most cases, are rare false/positive:
<IfModule mod_reqtimeout.c>
RequestReadTimeout header=10-40,MinRate=500 body=10,MinRate=500
</IfModule>
The rule below for mod_security was taken from the internet (and is optional, only mod_reqtimeout is enough), but works very well against this type of attack, should be used in conjunction with Modreqtimeout.
SecRule RESPONSE_STATUS "@streq 408" "phase:5,t:none,nolog,pass,
setvar:ip.slow_dos_counter=+1, expirevar:ip.slow_dos_counter=60, id:'5000770'"
SecRule IP:SLOW_DOS_COUNTER "@gt 5" "phase:1,t:none,log,drop,
msg:'Client Connection Dropped due to high number of slow DoS alerts', id:'5000771'"
The above rule identifies when the HTTP server fires a 408 status code and tracks how many times it happened while keeping data in IP-based persistent storage so that it can correlate between requests. If this event happens more than 5 times in 60 seconds, subsequent requests for that IP address will be dropped by mod_security for a 1 minute period.
But listen to me!
Scales, Varnish Cache, Nginx
If your infrastructure has scales, Varnish Cache, Nginx, or any other type of gateway, you’ll need to use mod_remoteip and configure the X-Forwarded-For
correctly in the header for apache to be able to see the real IP of the user, otherwise the above rules will not work and may end up blocking the IP of your gateway.
It’s also important to know that you need to create ratelimits for your gateways, although my rule takes down the unwanted connection, in the case of the gateway, if it is ignored by the rule (which is correct), the request will pass and only during apache response that the connection will be dropped, not preventing a Dos attack (but saves resources from processing the page, which is good anyway).
Cloudlare
If you use or intend to use Cloudflare, you can also configure the real IP of the user using mod_remoteip through the header CF-Connecting-IP
, or use mod_cloudflare.
Firewall
It is very interesting to have a Firewall to work with mod_security, I recommend the CSF (Configserver Security & Firewall).
With it just define the LF_MODSEC =
in the configuration file.
The configuration value LF_MODSEC
is the number of hits needed to add the offensive IP to be blocked by the firewall. Set LF_MODSEC
like 5 would block the IP address after 5 locks in mod_security within the time period set in LF_INTERVAL
, which is set in one hour (3600 seconds) by default.
You can install something on the server not as an Apache module, but a firewall like CSF (http://configserver.com/cp/csf.html) ?
– Emerson Rocha
As a curiosity: I have worked with Apache servers that used anti-virus, reverse proxy and other technologies. They did not work because as they were poorly configured in the first access of PHP to the file system I ended up finding confidential data of the hosting. It’s not just using modules, but configuring well, especially the system, as I mentioned.
– Gustavo Rodrigues