Protegiendo a sshd de ataques de diccionario con netfilter

En mi última entrada, escribí acerca de un pequeño script que bloquea conexiones a direcciones IP hostiles. Es un script sencillo que solo usa las facilidades del filtro de paquetes para bloquear una lista conocida de subredes clase B; si se quiere bloquear otra dirección, es necesario añadirla a la lista . Esto es, creé un muro de fuego sin estado (stateless rules).

Pero lo que hace verdaderamente poderoso a netfilter es su capacidad de conservación de estado (stateful rules). Esto permite crear mecanismos de protección y filtrado que no dependen de una lista estática de direcciones IP si nó del comportamiento mismo de las fuerzas hostiles que nos atacan. En la jerga de la caballería mecánizada esto lo llaman “blindaje activo”. Como un ejemplo de ello pongo aquí un fragmento que me gusta usar y que encontré en un comentario a un how-to acerca de como usar DenyHosts que es otra solución, muy popular, de hecho mucho más popular, pero que no es muy práctica si el equipo en cuestión debe seguír una política estricta de no conectarse al exterior si no es absolutamente necesario. Créanme, en general, si el sistema sirve a un proceso crítico del negocio, ni siquiera las actualizaciones del sistema operativo justifican una conexión abierta a la intergüexxxxda esa.

Sin más el fragmento, explicadito:

# Primero creamos una cola (cadena) nueva en el sistema por la que
# dirigiremos el tráfico de nuestras conexiones SSH.
iptables -N SSH

# Le decimos a netfilter que todas las conexiones nuevas
# que lleguen a la cola INPUT dirijidas al puerto 22 sean
# redirigidas a la cola SSH.
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j SSH

# A las conexiones recientes que están en la cola SSH
# las marcamos con el nombre "ataquessh"
iptables -A SSH -m recent --name ataquessh --set

# Cuando una conexión reciente conocida que tiene la marca "ataquessh"
# en la cola SSH ha intentado conectarse 3 o más veces seguidas en
# los últimos 60 segundos la bloqueamos hasta el próximo
# chequeo (en 60 segundos). La idea es que un script se bloqueará
# solito y un cracker redomado se dará cuanta pronto que es una
# pérdida de tiempo hacer ataques directos al puerto 22. Esto no
# descarta que intente usar otros medios de entrada que si requieran
# de verdaderos conocimiento. Pero hemos descartado al 99.95% de
# los posible crackers ahí afuera.

iptables -A SSH -m recent  --update --seconds 60 \
    --hitcount 3 --name ataquessh -j DROP

Podemos aprender más de como usar --update combinado con --seconds y --hitcount en el sitio web de SnowMan, el autor del módulo ipt_recent, además de en este artículo sobre limitación de conexiones a sshd que aunque viejito tiene información válida e interesante.

Actualización: Arreglé algunos problemillas con el código.