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
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
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.
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
Reviewed by PDFREEBOOK
on
10:57
Rating:
Post a Comment