Protección de SSH con iptables
Ejemplos prácticos de iptables para proteger el acceso SSH.
iptables es una utilidad de línea de comandos y la interfaz estándar para gestionar el cortafuegos Netfilter integrado en el kernel de Linux. Permite crear y modificar reglas que controlan cómo se filtran y enrutan los paquetes de red. Para trabajar con iptables se requieren privilegios de root.
Conceptos fundamentales
Una regla consta de un criterio de coincidencia, una acción target y un contador de paquetes. Cuando un paquete entrante satisface el criterio, se aplica la acción y el contador se incrementa. Las reglas se evalúan en orden — la secuencia importa.
- Criterio — una expresión lógica que examina las propiedades del paquete y la conexión para determinar si la regla se aplica. Varios criterios se combinan mediante un AND lógico.
- Acción (target) — qué hacer con un paquete cuando coincide: aceptarlo, descartarlo, pasarlo a otra chain, etc.
- Contador — registra cuántos paquetes han coincidido con la regla y su tamaño total en bytes.
Una chain es una lista ordenada de reglas. Las chains existen en dos modalidades:
- Chains predefinidas — creadas automáticamente al inicializar una tabla. Cada una tiene una política por defecto que se aplica a cualquier paquete que no coincida con otras reglas. Los nombres de las chains predefinidas siempre van en mayúsculas:
PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING. - Chains definidas por el usuario — creadas manualmente, limitadas a su propia tabla. Se recomienda usar nombres en minúsculas para evitar confusión con las chains predefinidas y los targets.
Una tabla es un conjunto de chains agrupadas por propósito. Los nombres de las tablas van en minúsculas. Se especifica una tabla con el flag -t nombre_tabla — si se omite, iptables usa filter por defecto.
1. Limitación de conexiones (protección contra fuerza bruta)
Para protegerse contra ataques de fuerza bruta sobre contraseñas, puedes limitar el número de nuevas conexiones SSH desde una misma IP — por ejemplo, 2 intentos por minuto — y descartar todo lo que supere ese umbral.
## Crear la chain sshguard
/sbin/iptables -N sshguard
# Opcional: registrar los intentos bloqueados en el log
#/sbin/iptables -A sshguard -m state --state NEW -m recent --name SSH --rcheck --seconds 60 --hitcount 2 -j LOG --log-prefix "SSH-shield: "
# Descartar conexiones que superen el límite de frecuencia
/sbin/iptables -A sshguard -m state --state NEW -m recent --name SSH --update --seconds 60 --hitcount 2 -j DROP
# Aceptar y registrar la IP si está por debajo del límite
/sbin/iptables -A sshguard -m state --state NEW -m recent --name SSH --set -j ACCEPT
/sbin/iptables -A sshguard -j ACCEPT
## Enrutar todo el tráfico SSH a través de sshguard
/sbin/iptables -A INPUT -p tcp --dport 22 -j sshguard
Estas reglas se basan en el módulo de kernel recent, que gestiona listas dinámicas de direcciones IP. A continuación se explica qué hace cada opción:
--name name— el nombre de la lista de IP con la que trabajar (el valor por defecto esDEFAULT)--rcheck— comprueba si la IP del remitente está en la lista; devuelvefalsesi no se encuentra--update— igual que--rcheck, pero también actualiza el timestamp si la IP se encuentra en la lista--hitcount hits— devuelvetruecuando el recuento de paquetes desde una IP dada alcanza o supera el valor especificado; se usa con--rchecko--update--seconds seconds— define cuánto tiempo permanece una IP en la lista tras ser añadida--set— añade la IP del remitente a la lista, o actualiza su entrada si ya está presente--remove— elimina una IP de la lista; devuelvefalsesi no se encuentra
Importante
Usar --update en lugar de --rcheck significa que cada nuevo intento de conexión reinicia el temporizador. Si alguien sigue intentándolo sin esperar, su cooldown de 60 segundos vuelve a empezar desde cero cada vez.
2. Apertura y cierre dinámico del puerto (port knocking)
En lugar de dejar SSH expuesto continuamente, puedes ocultarlo tras una secuencia de knock. El puerto se abre únicamente para la IP que envía el knock correcto — y se cierra de nuevo bajo demanda.
Para abrir el acceso SSH, conéctate primero al puerto 1500 — mediante telnet:
telnet myserver 1500
o directamente desde un navegador:
http://192.168.0.100:1500
Para cerrarlo de nuevo, llama al puerto 1499.
iptables -N sshguard
# Permitir la conexión si la IP ya está en la lista
iptables -A sshguard -m state --state NEW -m recent --rcheck --name SSH -j ACCEPT
# Permitir paquetes de conexiones ya establecidas
iptables -A sshguard -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A sshguard -j DROP
# Apertura: añadir la IP a la lista cuando se golpea el puerto 1500
#iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 1500 -j LOG --log-prefix "SSH-open: "
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 1500 -m recent --name SSH --set -j DROP
# Cierre: eliminar la IP de la lista cuando se golpea el puerto 1499
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 1499 -m recent --name SSH --remove -j DROP
## Enrutar el tráfico SSH a través de sshguard
iptables -A INPUT -p tcp --dport 22 -j sshguard
El acceso se concede únicamente a la IP que realizó el knock.
3. Acceso SSH por tiempo limitado
Este enfoque permite abrir SSH para una IP específica durante un período de tiempo fijo — útil cuando necesitas acceso temporal sin dejar un puerto permanentemente expuesto.
## Crear y vaciar la chain sshguard
iptables -N sshguard
iptables -F sshguard
# Permitir la conexión si la IP está en la lista y fue vista por última vez en las últimas 30 horas (108000 segundos)
iptables -A sshguard -m state --state NEW -m recent --update --seconds 108000 --name SSH -j ACCEPT
# Permitir paquetes de conexiones ya establecidas
iptables -A sshguard -m state --state ESTABLISHED,RELATED -j ACCEPT
# Descartar todo lo demás
iptables -A sshguard -j DROP
## Registrar la IP cuando se accede al puerto 222
iptables -A INPUT -m state --state NEW -p tcp --dport 222 -m recent --name SSH --set
## Enrutar el tráfico SSH a través de sshguard
iptables -A INPUT -p tcp --dport 22 -j sshguard
Para obtener acceso, conéctate primero al puerto 222:
ssh user@server.name -p 222
Después de eso, tu IP tendrá acceso SSH durante el período especificado. Cada conexión SSH posterior renueva el temporizador. Si prefieres no extender la ventana en cada conexión, sustituye --update --seconds 108000 por --rcheck.
El acceso se concede únicamente a la IP que realizó la conexión inicial.
Para ver qué IPs tienen acceso SSH en este momento:
cat /proc/net/ipt_recent/SSH
Ayuda
¿Tienes dudas o necesitas ayuda? Escríbenos a través del sistema de tickets — siempre estamos aquí para ayudarte!