Blog de Óscar

El Ingeniero de Sistemas Exóticos

Limitar conexiones con iptables recent

En ocasiones puede ser interesante limitar el numero de conexiones que se pueden realizar a un servicio en un tiempo específico. Por ejemplo para detener alguna suerte de bot que nos esta machacando nuestro puerto SSH.

Imaginemos el caso específico, nos están entrando conexiones desde una o varias IPs a un ritmo absurdamente alto. Lo mejor en esos casos es directamente hacer DROP de esas conexiones. Pues bien, usando el módulo recent de iptables podemos establecer dicha limitación de manera automática.

Estableciendo los límites

Queremos protegernos de un ataque de fuerza bruta a nuestro SSH. Sabemos que nosotros mismos no hacemos mas de cuatro conexiones a nuestro servidor en diez minutos, por lo que queremos establecer un límite para que a partir de la quinta conexión que reciba nuestra máquina en dicho periodo de tiempo automáticamente se bloquee y no permita nuevas conexiones durante exactamente el mismo periodo de tiempo.

iptables -N SSH
iptables -A SSH -m recent --set --name SSH
iptables -A SSH -m recent --update --seconds 600 --hitcount 5 --name SSH --rsource -j LOG --log-prefix "SSH-Bruteforce: "
iptables -A SSH -m recent --update --seconds 600 --hitcount 5 --name SSH --rsource -j DROP

La primera línea simplemente crea una nueva cadena que será la que mas tarde aplicaremos al puerto que nos interese proteger.

La segunda línea establece un tabla recent con nombre SSH donde se va a almacenar toda la información de las conexiones que entren por esta cadena. Esta tabla se almacena en /proc/net/xt_recent/SSH.

La tercera y cuarta línea están un poco relacionadas. Establecen que si en un periodo de 600 segundos (10 minutos) hay cinco o mas hits (entradas en la cadena desde la misma IP origen), por un lado se registra en el log con el prefijo indicado y por el otro se hace un DROP de la conexión. Esto se hace durante el mismo tiempo especificado, es decir, que en cuanto se supera el umbral de hitcount el contador de tiempo se pondrá a cero y hará LOG y DROP durante 600 segundos.

Ahora que ya tenemos la cadena con los límites simplemente tenemos que aplicarla.

iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -j SSH

Con esto indicamos todas las conexiones nuevas que nos entren vía eth0, de tipo TCP y por el puerto 22, acaben en la cadena SSH.

Modificar manualmente la tabla

Como comenté anteriormente, la tablas recent se almacenan en /proc/net/xt_recent/*, en nuestro caso concreto, al haber llamado a la tabla SSH, el fichero será /proc/net/xt_recent/SSH.

Podemos hacer cat a este fichero para que nos muestre las entradas que tiene almacenada la tabla, el resultado será algo similar a lo siguiente.

src=171.67.70.86 ttl: 239 last_seen: 83160859 oldest_pkt: 1 83160859
src=103.89.90.194 ttl: 110 last_seen: 82816546 oldest_pkt: 1 82816546
src=103.89.91.179 ttl: 110 last_seen: 82273441 oldest_pkt: 2 82273373, 82273441
src=153.120.93.172 ttl: 107 last_seen: 82600583 oldest_pkt: 1 82600583

Podemos modificar la tabla para añadir nuevas entradas, borrar las existentes o simplemente eliminarla. Siendo addr una dirección IP.

  • echo +addr >/proc/net/xt_recent/SSH: Añade una entrada en la tabla
  • echo -addr >/proc/net/xt_recent/SSH: Elimina una entrada de la tabla
  • echo / >/proc/net/xt_recent/SSH: Hace flush del fichero, o lo que es lo mismo, limpia completamente la tabla.

Sobre esto hay que tener en cuenta dos cuestiones.

  1. Cada echo +addr añade un hit, por lo que si nuestro límite esta establecido a cinco hits tendremos que hacer cinco veces el citado echo.
  2. El echo -addr borra la entrada completamente, independientemente del número de hits que tenga.

Conclusión

Como podemos ver iptables nos permite de manera sencilla establecer filtros para no permitir que se superen ciertos umbrales y paliar los efectos de un posible ataque por fuerza bruta. En los ejemplos anteriores establecemos los límites para el puerto 22 usado por el SSH, pero podríamos utilizar cualquier otro puerto como el 80 y 443 para el HTTP(s) o el 25 de SMTP.

Por último comentar que si necesitas un extra de protección que añada algo mas de inteligencia, puedes echarle un vistazo a Fail2ban.