Actualizado. Revisad las opciones que os deja escoger (limite de baneos, log, whitelist, etc...) y sobretodo aumentad el tamaño del buffer del log, esta comentado en el script.
#!/bin/sh
#============================================================================================================
# Descargado de: https://foro.seguridadwireless.net/openwrt/script-baneador-de-direcciones-ip-ssh-para-openwrt/
# Descargado de: https://foro.seguridadwireless.net/openwrt/script-baneador-de-direcciones-ip-ssh-para-openwrt/20/
# Descargado de: https://foro.seguridadwireless.net/openwrt/script-baneador-de-direcciones-ip-ssh-para-openwrt/40/
# Script realizado inicialmente por hardwarer para el foro de seguridadwireless.net
# Este script lee del log los fallos de autentificacion SSH (por usuario o contraseña erronea)
# Si los fallos exceden de cierta cantidad, banea su IP de origen utilizando iptables
# Tiempo de baneo configurable y tablas de baneo de IP permanentes al reinicio del sistema.
# Probado en OpenWrt 15.05.1 Chaos Chalmer y LEDE 17.01 (El original se probo en Openwrt 14.04 Barrier Breaker)
# Modificaciones Tki2000 (2017-05-15)
# Modificaciones David (2017-09-20) (Retocadas las funciones originales + puntos 5, 6, 7 y 8)
# Modificaciones David (2017-09-23) (9)
# Modificaciones David (2017-09-30) (10 + correccion de errores + cambio nombres de variables para legibilidad y asemeje a fail2ban original
#
# 1.- El fichero de baneos se escribe /tmp/, del que OpenWRT carga en RAM y asi no machaca la flash del router
# 2.- Si grabamos previamente el 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)
# 5.- Puede leer el log n lineas hacia atras para ver si esa ip ha tenido un acceso correcto y omitir su baneo
# 6.- Se puede anadir ips a una lista blanca para omitir baneo en caso de que tengas dedazos gordos.
# 7.- Se pueden anadir DNS a la lista blanca para omitir baneo (Requiere paquete hostip para resolver los dns)
# 8.- A la hora de quitar los baneos, revisa que tenga el comentario para evitar eliminar una regla que no toca
# 9.- Opcion a registrar en el log los baneos y unbaneos
# 10.- Modo Debug en el que no aplica las reglas del firewall, en su lugar imprime lo que haria (tampoco escribira la accion en el log)
#
# ======= A tener en cuenta =========
# Puede estar anadiendo y quitando constantemente un baneo si el log no rota, tiene un buffer pequeno o el tiempo de baneo es corto (amplia buffer, abajo detallo)
# Por defecto el log registra solo unas 340 lineas y perderias accesos no autorizados al rotar el log. Anade en la seccion "config system" del fichero /etc/config/system
# option log_buffer_size 256 # Por defecto toma 16 y con 256 amplia a unas 5000 lineas y 512 unas 10.000 (no poner mas de 999 ya que se comporta erroneo)
# Si cambiamos el ambito de bloqueo(chain) y todavía quedan reglas andidas, no seran eliminadas, aunque pase el tiempo de unbaneo. Borrar a mano o reiniciar
# Puede que no te banee por tener un acceso reciente pero que pasadas las lineas de busqueda seleccionadas ya no lea tu acceso y no omita el baneo.
# Lo ideal seria resetear y no buscar fallos hacia atras después de un acceso correcto de esa ip (pendiente por hacer, pero asi ya me funciona bien)
#
#============================================================================================================
#========================================== OPCIONES ========================================================
# Tiempo de baneo (en segundos). Transcurrido ese tiempo se desactiva el baneo y se quita la IP de la lista.
ban_time=36000 # 36000 = 10h, por defecto para pruebas # 86400 = Un dia = 24 horas # Dos semanas = 86400 * 14 = 1209600
# Definicion de las rutas de los ficheros que se usan en el script.
file_running="/tmp/fail2ban.run" # Para saber si se ha ejecutado al menos una vez (para carga inicial). Almacenar en /tmp/
file_banapplied="/tmp/banned.ips" # Fichero de baneos. Almacezar siempre en /tmp/ para asegurar que se escribe en RAM
file_banstored="/etc/fail2ban/banned.ips" # Es el fichero banapplied que podemos guardar a flash antes de reiniciar para volver a comenzar los baneos donde los dejamos
file_banstatic="/etc/fail2ban/banned_static.ips" # Para anadir manualmente ips que queramos banear desde el principio y de manera indefinida (Una IP o CIDR por línea)
# Whitelist de ips a omitir en el baneo
MyIPs=$(ifconfig | grep "inet addr" | awk '{ print $2}' | cut -d ":" -f 2 | xargs) # Tomara todas las ips locales del router (LAN,WAN,local y VPN levantadas)
WhitelistIPs="192.168.1.111 192.168.1.111" # Anade Ips que omitira al baneo. Para mas de una, anadir con un espacio
WhitelistDNS="oficina1.tudnsdeofi.com myhomeip.tudnsdcasa.com" # Anade DNS que omitira al baneo. Requiere hostip para resolver los DNS
WhitelistIPs="$MyIPs $WhitelistIPs $(for DNS in $WhitelistDNS; do hostip $DNS; done | xargs)" # Sumara todas las ips de lista blanca e ips de DNS de arriba
maxtretry=4 # Cuantos fallos de contrasena o usuario inexistente ha de encontrar en el log para banear a la ip
LinesToFindAcces=2000 # Cuantos eventos revisa atras en el log para ver si hay un acceso correcto de esa ip. Si lo hay, no la baneara. 0 para infinito
Comentario="BRUTEBAN" # Comentario que ira asociado a la regla anadida a iptables para distinguirla
WriteLogWithAction=1 # 1 para escribir en el log cuando banea o unbanea una ip. Cualquier otra cosa para omitir. (Con Debug activo no escribira en log)
WriteLogTag="f2b_action" # Tag al escriir en log el baneo o unbaneo (si lo has activado con WriteLogWithAction=1)
Debug="False" # Con "True" no aplica ni quita las reglas en iptables. En su lugar imprime lo que haria sin aplicarlas en el sistema. Cualquier otra cosa para normal
# Ambito/cadena de iptables donde se aplicaran los baneos. Local="input_lan_rule" internet="input_wan_rule" Ambas="input_rule"
chain="input_wan_rule" # Local="input_lan_rule" internet="input_wan_rule" Ambas="input_rule" # Por defecto deja "input_wan_rule" para hacer pruebas con seguridad desde lan
#=============================================================================================================
#====================================== CRONIFICAR =====================================================
# Copiar en /etc/fail2ban/fail2ban_openwrt.sh y dar permisos d ejecución: chmod +x /etc/fail2ban/fail2ban_openwrt.sh
# Para que se lance cada 10 minutos copia la tercera linea de abano editando con "crontab -e" o en luci "Sheluded Tasks"
# */10 * * * * /etc/fail2ban/fail2ban_openwrt.sh >> /dev/null 2>&1
#=============================================================================================================
#===================================== Codigo generico ==================================================
fecha_actual=`date +%s`
unban_date=`expr $fecha_actual + $ban_time`
#=============================================================================================================
#===================================== 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 $file_running ]; then
touch $file_running
if [ -f $file_banstatic ]; then
[ -f $file_banapplied ] && rm $file_banapplied
for x in `cat $file_banstatic | awk '{print $1}' FS=":"`; do
echo 2100000000:$x >> $file_banapplied
done
fi
if [ -f $file_banstored ]; then
for l in `cat $file_banstored | awk '{print $2}' FS=":"`; do
exists=`cat $banfile | grep $l | wc -l`
if [ "$exists" -lt 1 ]; then
echo "$unban_date:$l" >> $file_banapplied
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
[ ! -f $file_banapplied ] && touch $file_banapplied
for x in `cat $file_banapplied | awk '{print $2}' FS=":"`; do
if [ "$Debug" == "True" ];then
echo "Anade Baneo: iptables -I $chain 1 -s $x -j DROP -m comment --comment \"${Comentario}\""
else
iptables -I $chain 1 -s $x -j DROP -m comment --comment "${Comentario}" #:${fecha_actual}:${unban_date}"
[[ "$WriteLogWithAction" == "1" ]] && logger -t tag "$WriteLogTag" "Recuperado baneo en inicio a ip ${x}"
fi
done
fi
#================================================================================================
#====================== BANEO INTENTOS USUARIOS NO VALIDOS Y MAL PASSWORD =======================
# Entraran al for aquellas ips que hayan excedido mas del numero $Trigger los fallos de contrasena y usuario"
for badip in `logread | grep -e 'Login attempt for nonexistent user' -e 'Bad password' | cut -d':' -f 4 | cut -d ' ' -f 8 | uniq -c -f 7 | awk '{ if ( $1 > '$maxtretry' ) print $2}'`; do
# Si la direccion IP no esta en la lista de baneados, ni en la de recientes accesos correctos ni en la lista blanca, la anadimos a iptables
# if ! [ "$(grep $badip $file_banapplied)" ] && ! [ "$(logread -l $LinesToFindAcces -e 'Password auth succeeded' | cut -d ':' -f 4 | cut -d ' ' -f 8 | grep $badip)" ] && ! [[ "$WhitelistIPs" == *"$badip"* ]] ; then # La consola de openwrt es ash y no soporta el like con [[ "algo" == *"algo"* ]] cambiada por linea de abajo
if ! [ "$(grep $badip $file_banapplied)" ] && ! [ "$(logread -l $LinesToFindAcces -e 'Password auth succeeded' | cut -d ':' -f 4 | cut -d ' ' -f 8 | grep $badip)" ] && ! $(echo "$WhitelistIPs" | grep -q "badip") ; then
if [ "$Debug" == "True" ];then
echo "Anade Baneo: iptables -I $chain 1 -s $badip -j DROP -m comment --comment \"${Comentario}\""
else
iptables -I $chain 1 -s $badip -j DROP -m comment --comment "${Comentario}" #:${fecha_actual}:${unban_date}"
[[ "$WriteLogWithAction" == "1" ]] && logger -t tag "$WriteLogTag" "Baneo a ip ${badip}"
# Anadimos la IP al archivo de baneados "$file_banapplied" y la hora a la que terminara el baneo de esa IP en formato epoch (segundos desde 01-01-1970)
echo "$unban_date:$badip" >> $file_banapplied;
fi
fi
done
#================================================================================================
#======================== BORRADO DE BANEO TRANSCURRIDO EL TIEMPO ASIGNADO ======================
# Comprueba si alguno de los registros del fichero $file_banapplied tiene una fecha anterior a la actual. En caso afirmativo borra las reglas de iptables
for z in `cat $file_banapplied`; 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' $file_banapplied
unban_rule=`iptables -L $chain -n --line-numbers | grep "${Comentario}" | grep -m 1 $unban_ip|awk '{print $1}'`
if [ "$Debug" == "True" ];then
echo "Anade Baneo: iptables -D $chain $unban_rule -m comment --comment \"${Comentario}\""
else
iptables -D $chain $unban_rule -m comment --comment "${Comentario}"
[[ "$WriteLogWithAction" == "1" ]] && logger -t tag "$WriteLogTag" "Unbaneo a ip ${z}"
fi
fi
done