miércoles, febrero 11, 2015

Protegiendo el servidor SSH con fail2ban

Configurando fail2ban

Dados los repetidos ataques de fuerza bruta que estoy sufriendo al puerto SSH de mi raspberry pi por parte de ciertas ips desde china he revisado algunos sistemas de protección adicional además de los que ya implementé en su día.

De entre ellos el método más sencillo y que me está resultado más divertido en la instalacion de fail2ban. Este software revisa los logs de diversos servicios autentificados (ssh, apache, smtp...) buscando ataques de fuerza bruta y bloqueando las ips hostiles mediante la introducción de reglas en el iptables. Se pueden seleccionar los servicios que se quieren examinar (fails) y determinar las políticas (o acciones) que se que quieren emprender.

Pero vamos directamente al tema. La instalación básica ya nos servirá:

$sudo apt-get update
$sudo apt-get install fail2ban

Como siempre los ficheros de configuración están en /etc, vamos a darle un vistazo a /etc/fail2ban/jail.conf buscando concretamente estas dos secciones

...
# The DEFAULT allows a global definition of the options. They can be overridden
# in each jail afterwards.

[DEFAULT]

# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1/8
bantime  = 60000
maxretry = 3

...
[ssh]

enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 6

En negrita he marcado las partes que más interesan. Puedes ver que he fijado que la acción por defecto es bannear durante 1 hora, que salta al tercer error detectado y lo he activado para el servicio ssh. Salvo el tiempo de baneo todas las demás opciones estaban fijadas por defecto y el servicio ya está en marcha. Si haces cambios en la configuración recuerda reiniciarlo con sudo service fail2ban restart.

Pasado un tiempo podrás ver qué está haciendo examinando el log de fail2ban...

$ cat /var/log/fail2ban.log 
...
2015-02-11 06:52:14,590 fail2ban.server : INFO   Changed logging target to /var/log/fail2ban.log for Fail2ban v0.8.6
2015-02-11 06:52:14,602 fail2ban.jail   : INFO   Creating new jail 'ssh'
2015-02-11 06:52:14,665 fail2ban.jail   : INFO   Jail 'ssh' uses Gamin
2015-02-11 06:52:15,011 fail2ban.filter : INFO   Added logfile = /var/log/auth.log
2015-02-11 06:52:15,022 fail2ban.filter : INFO   Set maxRetry = 6
2015-02-11 06:52:15,038 fail2ban.filter : INFO   Set findtime = 600
2015-02-11 06:52:15,047 fail2ban.actions: INFO   Set banTime = 60000
2015-02-11 06:52:15,800 fail2ban.jail   : INFO   Jail 'ssh' started
2015-02-11 08:11:08,505 fail2ban.actions: WARNING [ssh] Ban 183.136.216.4
2015-02-11 10:05:25,417 fail2ban.actions: WARNING [ssh] Ban 183.136.216.3
2015-02-11 11:58:04,950 fail2ban.actions: WARNING [ssh] Ban 115.239.228.9

... o directamente comunicando con el proceso...

$ sudo fail2ban-client status ssh
Status for the jail: ssh
|- filter
|  |- File list: /var/log/auth.log 
|  |- Currently failed: 1
|  `- Total failed: 22
`- action
   |- Currently banned: 3
   |  `- IP list: 183.136.216.4 183.136.216.3 115.239.228.9 
   `- Total banned: 3

Puedes comprobar cómo ha intoducido las reglas en el iptables con

$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
fail2ban-ssh  tcp  --  anywhere             anywhere             multiport dports ssh

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain fail2ban-ssh (1 references)
target     prot opt source               destination         
DROP       all  --  115.239.228.9        anywhere            
DROP       all  --  183.136.216.3        anywhere            
DROP       all  --  183.136.216.4        anywhere            
RETURN     all  --  anywhere             anywhere   

Yo me he hecho un pequeño script lllamdo f2b_status.sh para de un sólo vistazo comprobar la última actividad del fail2ban

#!/bin/bash
echo
echo "---------------"
echo "Fail2Ban report"
echo "---------------"
echo
echo "Last 20 lines of fail2ban.log"
echo "-----------------------------"
cat /var/log/fail2ban.log | tail -n 20 
echo
echo "fail2ban service status"
echo "-----------------------" 
sudo fail2ban-client status ssh
echo
exit 0

Cómo crear baneos permanentes a ciertas ips

Lo único malo de los baneos es que se acaban (salvo que pongamos bantime  = -1) y es interesante poder introducir reglas que baneen ips definitivamente. Hay una manera muy sencilla: crear un archivo /etc/fail2ban/ip.blacklist y poner una ip por línea (no añadir un retorno de carro al final del archivo o generará un error)

Después abrimos el fichero de la acción por defecto, que si no lo hemos alterado debería ser /etc/fail2ban/action.d/iptables-multiport.conf, y dejar la acción que ejecuta al inicio "actionstart" como sigue:

actionstart = iptables -N fail2ban-
              iptables -A fail2ban- -j RETURN
              iptables -I -p -m multiport --dports -j fail2ban-
              cat /etc/fail2ban/ip.blacklist | while read IP; do iptables -I fail2ban- 1 -s $IP -j DROP; done

Ahora, cada vez que iniciemos el servicio baneará directamente las ips que encuentre el ip.blacklist. Puedes banear rango enteros, algunos ejemplos:


$ cat /etc/fail2ban/ip.blacklist 
183.136.216.4
183.136.216.3
115.239.228.9
115.239.228.0/24

Baneando IPs permanentemente de forma automática

Si como yo te estás hartando de meter manualmente ciertas ips en el blacklist podemos utilizar otra aproximación al problema. Primero: hacer todos los baneos permanentes con bantime=-1,  ten en cuenta que seguirás necesitando usar ip.blacklist para conservar las ips bloqueadas al reiniciar el servicio. Segundo: hacer que  la acción de banear añada directamente la IP al ip.blacklist.

MUCHO OJO:   si no tienes acceso físico al servidor asegúrate de incluyes alguna ip que tengas controlada en ignoreip, podría darse el caso de que un día te equivoques tres veces con la contraseña ¡y no puedas acceder nunca más!

Vamos al lío, comenzamos cambiando /etc/fail2ban/jail.conf

[DEFAULT]

# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1/8 192.168.0.0/24
bantime  = -1
maxretry = 3

Hemos fijado el bloqueo a permanente y añadido una regla para que ignore los fallos que provengan de la red local. Vamos a cambiar las acciones del /etc/fail2ban/action.d/iptables-multiport.conf, vamos a alterar actionstart y actionban

...

actionstart = iptables -N fail2ban-
              iptables -A fail2ban- -j RETURN
              iptables -I -p -m multiport --dports -j fail2ban-
              cat /etc/fail2ban/ip.blacklist | while read IP; do iptables -I fail2ban- 1 -s $IP -j DROP; done

...

actionban = if ! iptables -C fail2ban- -s -j DROP; then iptables -I fail2ban- 1 -s -j DROP; fi
            # Add offenders to local blacklist, if not already there
            if ! grep -Fxq ',' /etc/fail2ban/ip.blacklist; then echo ',' >> /etc/fail2ban/ip.blacklist; fi

...

Ahora cada vez que banee una ip lo hará de una forma permamente y la incluirá dentro del ip.blacklist. Por el momento si quieres eliminar una IP del blacklist deberás hacerlo manualmente editando el archivo y reiniciando el servicio.

Otra aproximación al problema más avanzada es banear permanentemente sólo aquellas ips que te den problemas de forma reiterada, por ejemplo, aquellas que ya has baneado dos o tres veces. Para eso estás obligado a crear un nuevo jail que, en este caso examine los propios logs del fail2ban buscando las ips hostiles. No estoy seguro de que sea la aproximación más adecuada, introduce más carga de trabajo en el fail2ban y además los hostiles suelen utilizar conjuntos de ips para realizar los ataques con lo cual puedes recibirlos desde varios cientos de IPs. En cualquier caso tienes una buena descripción de la estrategia en este artículo.

No hay comentarios:

Publicar un comentario