DDoS Deflate, script bash para mitigar ataques DoS

Básicamente lo único que hace el script bash es un netstat para ver el número de conexiones abiertas en el puerto que sea (no sólo nos protege de ataques http, también de otro tipo de conexiones simultáneas a otros puertos).

netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n


Si el resultado del comando detecta más de n conexiones de una misma ip la banea automáticamente mediante iptables, añadiendo una entrada en iptables  con la instrucción:



iptables -D INPUT -s $ip -j DROP

Instalación


wget http://www.inetbase.com/scripts/ddos/install.sh
chmod 0700 install.sh
./install.sh

Lo que hace el script es bajar los ficheros de configuración y el propio script y copiarlos al directorio 

/usr/local/ddos 

#!/bin/sh
if [ -d '/usr/local/ddos' ]; then
    echo; echo; echo "Please un-install the previous version first"
    exit 0
else
    mkdir /usr/local/ddos
fi
clear
echo; echo 'Installing DOS-Deflate 0.6'; echo
echo; echo -n 'Downloading source files...'
wget -q -O /usr/local/ddos/ddos.conf http://www.inetbase.com/scripts/ddos/ddos.conf
echo -n '.'
wget -q -O /usr/local/ddos/LICENSE http://www.inetbase.com/scripts/ddos/LICENSE
echo -n '.'
wget -q -O /usr/local/ddos/ignore.ip.list http://www.inetbase.com/scripts/ddos/ignore.ip.list
echo -n '.'
wget -q -O /usr/local/ddos/ddos.sh http://www.inetbase.com/scripts/ddos/ddos.sh
chmod 0755 /usr/local/ddos/ddos.sh
cp -s /usr/local/ddos/ddos.sh /usr/local/sbin/ddos
echo '...done'

echo; echo -n 'Creating cron to run script every minute.....(Default setting)'
/usr/local/ddos/ddos.sh --cron > /dev/null 2>&1
echo '.....done'
echo; echo 'Installation has completed.'
echo 'Config file is at /usr/local/ddos/ddos.conf'
echo 'Please send in your comments and/or suggestions to zaf@vsnl.com'
echo
cat /usr/local/ddos/LICENSE | less

 En el fichero de configuración ddos.conf del directorio /usr/local/ddos

 ##### Paths of the script and other files
PROGDIR="/usr/local/ddos"
PROG="/usr/local/ddos/ddos.sh"
IGNORE_IP_LIST="/usr/local/ddos/ignore.ip.list"
CRON="/etc/cron.d/ddos.cron"
APF="/etc/apf/apf"
IPT="/sbin/iptables"

##### frequency in minutes for running the script
##### Caution: Every time this setting is changed, run the script with --cron
#####          option so that the new frequency takes effect
FREQ=1

##### How many connections define a bad IP? Indicate that below.
NO_OF_CONNECTIONS=150

##### APF_BAN=1 (Make sure your APF version is atleast 0.96)
##### APF_BAN=0 (Uses iptables for banning ips instead of APF)
APF_BAN=0

##### KILL=0 (Bad IPs are'nt banned, good for interactive execution of script)
##### KILL=1 (Recommended setting)
KILL=1

##### An email is sent to the following address when an IP is banned.
##### Blank would suppress sending of mails
EMAIL_TO="webmaster@elhacker.net"

##### Number of seconds the banned ip should remain in blacklist.
BAN_PERIOD=600

Nota: Si tenemos un servidor con muchas descargas de ficheros grandes (ejemplo isos) puede ser que algún cliente legítimo (falso positivo) usando alguna herramienta de descargas alcance 150 conexiones en el servidor web).


Por defecto el programa añade una entrada en cron jobs para ejecutarse cada minuto y si detecta una ip con más de 150 conexiones la banea durante un período de 600  segundos (10 minutos), manda un e-mail a root (podemos editar el email de root en el fichero /etc/aliases) añadiendo una entrada:

root: webmaster@elhacker.net

El script mira si una ip tiene más de 150 conexiones abiertas y la banea automáticamente durante 10 minutos. 
La entrada del cron job se añade en /etc/cron.d con el nombre ddos.cron

 SHELL=/bin/sh
0-59/1 * * * * root /usr/local/ddos/ddos.sh >/dev/null 2>&1

En el fichero /usr/local/ddos/ignore.ip.list podemos definir la lista blanca de ip's que serán ignoradas aunque tengan más de 150 conexiones. Sería una buena idea añadir nuestra propia ip

127.0.0.1
144.76.224.7

 Si el script detecta una ip atacante nos enviará un e-mail con el asunto "IP addresses banned", la fecha de la detección y la ip baneada con el número de conexiones que ha detectado.

IP addresses banned on Mon Dec 23 21:46:01 CET 2013
Banned the following ip addresses on Mon Dec 23 21:46:01 CET 2013
192.147.213.222 with 453 connections


Podemos ver con el comando iptables las reglas actuales activas para ver como la ip atacante ha sido añadida:

iptables -L

 Resultado, entrada añadida para la ip 192.147.213.222

DROP       all  --  192.147.213.222  anywhere   

También podemos añadir de forma permanente la ip baneada añadiendo una entrada al fichero /etc/sysconfig/iptables

-A INPUT -s 192.147.213.222 -j DROP

Si el script banea ip's incorrectas (del tipo ::ffff)

netstat -ntu | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -nr > $BAD_IP_LIST

deberíamos reemplazar la línea 117 por:

netstat -ntu | grep ‘:’ | awk ‘{print $5}’ | sed ‘s/::ffff://’ | cut -f1 -d ‘:’ | sort | uniq -c | sort -nr > $BAD_IP_LIST

De hecho los cambios  están en un fork en github:

https://github.com/chrisnharvey/DDoS-Deflate

O una versión muy similar pero re-escrita que añade nuevas opciones:

Reverso de ip's (reverso dns)
Posibilidad de avisar (warning) si son más de x conexiones y banear si son más x
Guardar un log con la fecha y las ip's baneadas
https://github.com/colinmollenhour/ddos-deflate

Aunque deberíamos quitar el grep ESTAB ( de Established), ya que si estamos recibiendo un ataque syn-flood, los estados podrían ser: SYN_RECV, TIME_WAIT, FIN_WAIT2, LAST_ACK

Línea 184:

netstat -ntu | grep ESTAB | grep ':' | awk '{print $5}' | sed 's/::ffff://' | cut -f1 -d ':' \ | sort | grep -v -f <(grep -vF '#' $IGNORE_IP_LIST | sort) | uniq -c \ | awk "{ if (\$1 >= $WARN_LIMIT) print; }" | sort -nr \
Cambiar por:

netstat -ntu | grep ':' | awk '{print $5}' | sed 's/::ffff://' | cut -f1 -d ':' \ | sort | grep -v -f <(grep -vF '#' $IGNORE_IP_LIST | sort) | uniq -c \ | awk "{ if (\$1 >= $WARN_LIMIT) print; }" | sort -nr \

Un script muy similar pero escrito en perl es Citadel
Desinstalación

wget http://www.inetbase.com/scripts/ddos/uninstall.ddos
chmod 0700 uninstall.ddos
./uninstall.ddos

O eliminar el cronjob y el directorio /usr/local/ddos

Otras maneras de detectar un ataque DoS

 Ordenar el número  de conexiones al puerto 80 de menor a mayor:

 netstat -an | grep :80 | awk '{ print $5 }' | awk -F: '{ print $1 }' | sort | uniq -c | sort -n

Ejemplo resultado en caso de un ataque:
       
[..] 
169 190.11.90.215
221 190.228.135.10
424 186.11.240.81
526 179.12.27.14 
Muy probablemente una ip con 526 conexiones o 424 nada bueno puede estar haciendo 

Contar número de peticiones abiertas en el servidor web (puerto 80) sea Apache o Nginx) 

netstat -an | grep :80|wc -l
Contar número de conexiones en estado SYN_RECV

netstat -an | grep :80 | grep -i syn | wc -l

Con iptables una de las maneras más sencillas pero efectivas de mitigar un ataque es con el módulo recent:

/sbin/iptables -I INPUT -p tcp -m state --state NEW --dport 80 -m recent --update --seconds 15 --hitcount 10 -j DROP

Ver las ip's conectadas sin usar netstat:

cat /proc/net/ip_conntrack | awk '{print $5" "$6}' | sort -nr | uniq -c

Ordenar por consumo de tráfico (bandwidth) usando iptables

/sbin/iptables -L -v -n | sort -n
 Limitar ataques SYN_Flood usando limit y limit-burst

Con iptables:

--limit rate[/second|/minute|/hour|/day] Maximum average matching rate: specified as a number, with an optional `/second’, `/minute’, `/hour’, or `/day’ suffix; the default is 3/hour.

--limit-burst

Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number; the default is 5.
iptables -N DDoS
iptables -A DDoS -m limit –limit 1/s –limit-burst 10 -j RETURN
iptables -A DDoS -j LOG –log-prefix “[Recibiendo ataque DDOS]“
iptables -A DDoS -j DROP

iptables -N syn-flood
iptables -A syn-flood -m limit --limit 50/second --limit-burst 100 -j LOG --log-prefix "Firewall syn-flood "
iptables -A syn-flood -j DROP
Con --limit se especifica una media, no un caudal. Por ejemplo: decir 3/minuto puede significar que en el primer minuto se reciben 3 paquetes y en el segundo también 3 o puede significar que en el primer minuto se reciben 5 y en el segundo 1... la media sigue siendo 3/minuto.

--limit-bust especifica un máximo, si no se especifica un --limit-burst por defecto vale 5 y significa que se aceptaran los primeros 5 paquetes y luego se esperara hasta alcanzar la media para seguir aceptando. Parece complicado pero no lo es.

Ejemplo: especificaste un --limit 3/segundo y un --limit-burst 6, entonces se aceptarán los primeros 6 paquetes, no importa que tan seguido vengan, luego se dejara de aceptar hasta alcanzar la media, es decir se esperará a que se cumplan 2 segundos y luego se volverá a permitir un máximo de 6.

-A INPUT -p tcp -m tcp --dport 80 -m limit --limit 75/second --limit-burst 120 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -m limit --limit 75/second --limit-burst 200 -j LOG
-A INPUT -p tcp -m tcp --dport 80 -j DROP

Con la herramienta (script floodmon)

Floodmon: alerta, detecta y mitiga ataques SYN Flood

Quizás sea el momento para instalar soluciones más avanzadas como  APF (Advanced Policy Firewall) o BFD (Brute Force Detect).

O usar servicios gratuitos como la CDN de CloudFlare que permite:


Ocultar la ip real (Usando las DNS de CloudFlare)
Crear un front end para la web (WAF (Web Application Firewall)
Bloquear visitantes por País (CloudFlare Threat Control Block list)
Crear reglas (Redireccionar http a https o viciversa, redireccionar una url con un 301 o 302, cachear)
Añadir test Captcha para verificar si son humanos o bots


Detectar patrones del tráfico recibido con tcpdump

tcpdump -nn 'tcp[13] == 2' and port 80 -c 100 -i any
tcpdump -Annvvs 1500 'tcp[13] == 2' and port 80 -c 100 -i any

Otras soluciones y contramedidas ya fueron vistas en el manual  de Intentando Detener un Ataque DDoS



Error en Apache que suele estar causado por denegación de servicio (DoS o distribuido DDoS)
[Mon Dec 23 07:19:34 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:35 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:39 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:40 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:40 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:19:46 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:20:05 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:21:07 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:21:11 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:21:22 2013] [error] [client 186.58.83.79] request failed: error reading the headers
[Mon Dec 23 07:21:25 2013] [error] [client 186.58.83.79] request failed: error reading the headers

Puede estar provocado por herramientas DoS bastante efectivas como Slowris o más rudimentarias como LOIC (Low Orbit Ion Cannon)



Si en el fichero de errores del Apache:
grep -i maxclient /usr/local/apache2/logs/error_log

Aparecen errores como:

server reached MaxClients setting, consider raising the MaxClients setting

Significa que el número de conexiones simultáneas del Apache (podemos verlo fácilmente con el server-status) ha sido alacanzado y deberíamos considerar aumentarlo, siempre y cuando tengamos recursos suficientes para hacerlo.
DDoS Deflate, script bash para mitigar ataques DoS DDoS Deflate, script bash para mitigar ataques DoS Reviewed by PDFREEBOOK on 10:57 Rating: 5

No hay comentarios

Los Comentarios emitidos en cada uno de los contenidos deberan ajustarse al tema tratado durante el post de lo contrario sera Eliminado