Ya que últimamente yo también he estado recibiendo ataques, a una de las redes que tengo por ahí perdida, y cumpliendo los deseos de
hardwarer,
Animo a todos a modificar el script y mejorarlo o lo que sea.
Me he decidido a meterle mano a este script, que llevo usando desde hace tiempo, y no sé si lo habré mejorado o no, pero a mi me está sirviendo para parar muchos ataques.
He modificado el lugar del fichero de baneos, para no machacar la flash del router, y le he añadido la opción de almacenar el fichero de baneos en flash, para continuar por donde íbamos, y un fichero de IPs manuales, para poner a mano las que queramos banear indefinidamente.
No he elaborado el fichero de instalación, como hizo
hardwarer. Es simplemente el script a pelo, en el que podemos definir las rutas de los distintos ficheros que vamos a usar.
En mi caso lo he instalado todo en /etc/fail2ban, ya que de esa forma lo guardo automáticamente cuando un backup de la configuración del router. Pero podéis grabarlo donde gustéis, siempre y cuando, cambiéis las rutas de los ficheros en el script.
El código es éste:
#!/bin/sh
#============================================================================================================
# SCRIPT
#============================================================================================================
# Script realizado por hardwarer, para el foro de seguridadwireless.net
# Este script detecta los intentos de conexion fallidos al servidor SSH, ya sea por contraseña erronea
# o por usuario no valido y protege el sistema baneando la IP de origen utilizando el cortafuegos de Linux Iptables.
# Tiempo de baneo configurable y tablas de baneo de IP permanentes al reinicio del sistema.
# Probado en OpenWrt 14.04 Barrier Breaker.
# Modificaciones Tki2000 (2017-05-15)
#
# 1.- El fichero de baneos se escribe en memoria RAM para no machacar la flash del router
# 2.- Si grabamos previamente un fichero de baneos, de la RAM a la flash, lo usará al inicio.
# 3.- Posibilidad de banear manualmente ips, además de las detectadas en el script, durante un tiempo indefinido.
# 4.- Las IPs repetidas, entre ficheros, no se tienen en cuenta nada más que una vez al banear. (2017-05-30)
#
# El fichero de baneos en la RAM, se encuentra por defecto en /tmp/banned.ips
# El fichero de baneos en la flash, se encuentra por defecto en /etc/fail2ban/banned.ips
# El fichero de baneos manual, se encuentra por defecto en /etc/fail2ban/banned_static.ips
# El formato del fichero de baneos manual, es de una IP por línea.
#
#============================================================================================================
#========================================== OPCIONES ========================================================
# Tiempo de baneo (en segundos). Transcurrido ese tiempo se desactiva el baneo y se quita la IP de la lista.
# 24 horas = 86400 segundos.
#ban_time=86400
# 86400 * 14 = 1209600
ban_time=1209600
# Definición de las rutas de los ficheros que se usan en el script.
# El fichero de banfile es el fichero de baneos y se maneja en memoria, para no machacar la flash del router.
# El fichero de banfile_stored es el fichero que podemos dejar grabado en la flash del router, para volver
# a comenzar los baneos, por donde los dejamos. Previamente, antes de reiniciar el router debemos
# grabar el fichero de la memoria, a la flash, claro.
# El fichero de banned_static, es un fichero para añadir manualmente ips que queramos desde el principio,
# para banearlos de manera indefinida. El formato es de una IP por línea.
banfile="/tmp/banned.ips"
banfile_stored="/etc/fail2ban/banned.ips"
banfile_static="/etc/fail2ban/banned_static.ips"
fail2ban_running="/tmp/fail2ban.run"
# Funcionamiento en internet, red local o ambas. Descomentar la opcion deseada. Por defecto solo internet.
# input_wan_rule= Solo internet (defecto), input_lan_rule= Solo red local, input_rule funcionamiento en ambas redes.
# Si cambiamos este valor debemos reiniciar el router.
alcance="input_wan_rule"
#alcance="input_lan_rule"
#alcance="input_rule"
#=============================================================================================================
#===================================== COMPROBACION INICIAL ==================================================
# Comprobamos si acabamos de iniciar el router y en ese caso preelaboramos el fichero de baneos
# Modificación : Si tenemos un fichero grabado previo, lo usamos.
# Modificación : Si tenemos un fichero de ips para banear estático, preelaboramos el fichero de baneos.
if [ ! -f $fail2ban_running ]
then
touch $fail2ban_running
if [ -f $banfile_static ]
then
if [ -f $banfile ]
then
rm $banfile
fi
for x in `cat $banfile_static | awk '{print $1}' FS=":"`
do
echo 2100000000:$x >> $banfile
done
fi
if [ -f $banfile_stored ]
then
for l in `cat $banfile_stored | awk '{print $2}' FS=":"`
do
exists=`cat $banfile | grep $l | wc -l`
if [ "$exists" -lt 1 ]
then
fecha_actual=`date +%s`
unban_date=`expr $fecha_actual + $ban_time`
echo "$unban_date:$l" >> $banfile
fi
done
fi
# Si es la primera vez que lanzamos el script, debemos crear el fichero donde se guardan
# las ips baneadas, si no lo hemos creado ya, en los procedimientos anteriores
if [ ! -f $banfile ]
then
touch $banfile
fi
for x in `cat $banfile | awk '{print $2}' FS=":"`
do
iptables -I $alcance 1 -s $x -j LOG --log-prefix "--ATAQUE--FUERZA--BRUTA--";
iptables -I $alcance 2 -s $x -j DROP;
done
fi
#=============================================================================================
#====================== BANEO INTENTOS USUARIOS VALIDOS Y MAL PASSWORD =======================
# Comprobamos las conexiones y el numero de veces que el resultado ha sido "Bad password"
for i in `logread | grep "Child connection" | awk '{print $11}' | awk '{print $1}' FS=":"`
do
brute=`logread | grep 'Bad password' | grep $i | wc -l`;
# Si son mas de tres veces guardamos la IP en la variable "badip"
if [ "$brute" -gt 3 ];
then
badip=`logread | grep "Bad password" | grep -m 1 $i | awk '{print $14}' | awk '{print $1}' FS=":"`
# Comprobamos si la direccion IP ya esta en la lista de baneados:
oldban=`cat $banfile | grep $badip | wc -l`;
# Si la IP no aparece en la lista la anadimos a iptables.
if [ "$oldban" -lt 1 ];
then
iptables -I $alcance 1 -s $badip -j LOG --log-prefix "--ATAQUE--FUERZA--BRUTA--";
iptables -I $alcance 2 -s $badip -j DROP;
# Por ultimo anadimos la IP al archivo de baneados "$banfile" y la hora a la
# que terminara el baneo de esa IP en formato epoch (segundos desde 01-01-1970)
fecha_actual=`date +%s`
unban_date=`expr $fecha_actual + $ban_time`
echo "$unban_date:$badip" >> $banfile;
fi;
fi;
done;
#================================================================================================
#============================== BANEO INTENTOS USUARIOS NO VALIDOS ==============================
# Comprobamos las conexiones y el numero de veces que el resultado ha sido "invalid shell"
for i in `logread | grep "Child connection"|awk '{print $11}' | awk '{print $1}' FS=":"'`
do
brute=`logread | grep -A 4 $i |grep "Login attempt for nonexistent" | wc -l`
if [ "$brute" -gt 3 ];
then
badip=`logread | grep "Child connection" | grep -m 1 $i | awk '{print $11}' | awk '{print $1}' FS=":"`
# Comprobamos si la direccion IP ya esta en la lista de baneados:
oldban=`cat $banfile | grep $badip | wc -l`
# Si la IP no aparece en la lista la anadimos a iptables.
if [ "$oldban" -lt 1 ];
then
iptables -I $alcance 1 -s $badip -j LOG --log-prefix "--ATAQUE--FUERZA--BRUTA--";
iptables -I $alcance 2 -s $badip -j DROP
# Por ultimo anadimos la IP al archivo de baneados "$destino/logfail.log" y la hora a la
# que terminara el baneo de esa IP en formato epoch(segundos desde 01-01-1970)
fecha_actual=`date +%s`
unban_date=`expr $fecha_actual + $ban_time`
echo "$unban_date:$badip" >> $banfile;
fi;
fi;
done;
#================================================================================================
#======================== BORRADO DE BANEO TRANSCURRIDO EL TIEMPO ASIGNADO ======================
# Un bucle comprueba si alguno de los registros del fichero logfail2.log tiene una fecha anterior
# a la actual. En caso afirmativo borra las reglas de iptables y los registros del log.
fecha_actual=`date +%s`
for z in `cat $banfile`
do
unban_time=`echo $z | awk -F ":" '{print $1}'`
unban_ip=`echo $z | awk -F ":" '{print $2}'`
if [ "$unban_time" -lt "$fecha_actual" ]
then
sed -i '/'$unban_ip'/d' $banfile
unban_rule=`iptables -L -n --line-numbers|grep -m 1 $unban_ip|awk '{print $1}'`
iptables -D $alcance $unban_rule
iptables -D $alcance $unban_rule
fi
done
Como siempre, usad estos datos, bajo vuestra propia responsabilidad.