SSHGuard – Alternativa a Fail2ban para proteger SSH contra ataques de fuerza bruta

Buscando temas relacionados con el soporte de IPv6 en Failban, que de momento ya sabemos que no tiene, acabé dando con una alternativa llamada SSHGuard escrita completamente en lenguaje C.

Cuenta con soporte para gran cantidad de formatos de log, de manera que puede leer syslog, syslog-ng, multilog… y además no sólo puede proteger contra ataques en el servicio SSH sino también Exim, Dovecot, Sendmail o vsftpd entre otros. El programa parsea los logs línea a línea buscando determinados patrones (como por ejemplo intentos de login con error) para bloquear al atacante.

Para ello, a la hora de bloquear se integra a nivel de firewall para insertar reglas de bloqueo en función del servicio protegido. En este sentido es compatible con una gran cantidad de firewalls: iptables, ipfw, ipfilter… e incluso puede integrarse con TCP wrappers -en los sistemas que no dispongan de firewall de red- para insertar bloqueos en ficheros /etc/hosts.allow

Lo podemos compilar desde código fuente o instalarlo como paquete binario, estando disponible para Debian, RHEL, ArchLinux,Open/FreeBSD…

En el caso que nos ocupa vamos a instalarlo en Debian desde repos:

apt-get install sshguard

Para integrarlo con iptables, introducimos las siguientes cadenas y reglas antes que el resto de reglas que tengamos. Es importante que respetemos el orden, ya que la cadena de sshguard tiene que figurar la primera y justo seguidas las reglas para que el tráfico entrante se filtre en la cadena sshguard:

# Creamos la cadena sshguard tanto para IPv4 como IPv6
iptables -N sshguard
ip6tables -N sshguard
# Justo a continuación, le pasamos lo que llegue a INPUT 
# a la cadena sshguard para que determine si se tiene que bloquear o no
iptables -A INPUT -j sshguard
ip6tables -A INPUT -j sshguard

Ahora, vamos a comprobar qué ficheros está monitorizando por defecto en /etc/default/sshguard

# Set the following varible to 0 in order to prevent Sshguard init script from
# changing the firewall rules; in such case you will need to setup such rules
# yourself according to the Sshguard documentation.
# See man page sshguard(8) for documentation of the command line options
ENABLE_FIREWALL=1

# list of log files to scan delimited by space
LOGFILES="/var/log/auth.log"

# Whitelist configuration file
WHITELIST="/etc/sshguard/whitelist"

# Other options
ARGS="-a 40 -p 420 -s 1200"

Por una parte tenemos /var/log/auth.log que es el fichero que nos interesa para proteger el servicio SSH. En la variable LOGFILES podríamos incluir otros logs de otros servicios a monitorizar. Para el caso que vamos a ver nos vale tal y como viene por defecto. En cuanto a los argumentos que aparecen al final:

  • -a → threshold a partir del cual se realiza el bloqueo. Tened en cuenta que por ejemplo un error de login por SSH originará una puntuación de 10. Por lo tanto, si el threshold está en 40, tendremos 4 intentos de login antes de que nos bloquee sshguard. Los patrones considerados como ataques podéis encontrarlo en la sección Attack Signatures de la documentación.
  • -p → nº de segundos que dura el bloqueo, en este caso 630 segundos. Te preguntarás por qué en el parámetro aparece 420. La razón es que para sshguard el tiempo de bloqueo se calcula con la fórmula 3/2 * X, siendo X el número en segundos que le pasamos al parámetro -p. En nuestro caso quedaría: 3/2 x 420 = 630
  • -s → nº de segundos que puede pasar entre un intento fallido y otro. Pongamos por ejemplo el caso de hacer un login fallido por SSH, esperar 1200 segundos y hacer otro fallido. Entonces, sshguard no lo tendría en cuenta como un ataque de fuerza bruta y no entraría en su cómputo para bloquear la IP en cuestión.

Vamos a ponerlo a prueba con un sencillo test. Intentamos una serie de logins sin éxito en la máquina protegida por sshguard y observamos lo siguiente en el /var/log/auth.log de dicha máquina:

sshd[17044]: Failed password for jota from 192.168.2.101 port 38108 ssh2
sshd[17044]: Failed password for jota from 192.168.2.101 port 38108 ssh2
sshd[17044]: Failed password for jota from 192.168.2.101 port 38108 ssh2
sshd[17044]: Connection closed by 192.168.2.101 [preauth]
sshd[17044]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.2.101  user=jota
sshd[17053]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.2.101  user=jota
sshd[17053]: Failed password for jota from 192.168.2.101 port 38109 ssh2
sshguard[16347]: Blocking 192.168.2.101:4 for >630secs: 40 danger in 4 attacks over 28 seconds (all: 40d in 1 abuses over 28s).

Vemos que ha bloqueado a 192.168.2.101 después de 4 intentos fallidos. Si hacemos un iptables -L deberíamos ver cómo se ha introducido la regla correspondiente en la cadena sshguard tal que así:

Chain sshguard (1 references)
target     prot opt source               destination
DROP       all  --  192.168.2.101        anywhere

El ejemplo anteriormente expuesto es para netfilter/iptables protegiendo el servicio SSH, pero podemos configurarlo para integrarlo con otros firewalls de otros sistemas Linux o tipo UNIX tal y como indican en la documentación.

Aunque no permite tanta granularidad de configuración como Fail2ban, podemos considerar SSHGuard una alternativa ligera y simple que nos protege de los típicos ataques de fuerza bruta en servicios críticos del sistema.