Hace poco visitando el blog de Vicente Navarro (todo un referente para mí, por el detalle y la claridad con la que redacta sus post), conocí esta herramienta y me pareció lo suficiente curiosa como para escribir este post.
El concepto no es nada nuevo, Martin Krzywinsk en Junio de 2003 publicó un artículo donde detallaba como realizar esto con los firewalls del kernel de linux. La idea es establecer una serie de puertos en el servidor y después desde un cliente intentar conectar a esos puertos en el orden establecido para que sepa que somos nosotros y entonces abrir otro puerto previamente establecido para darnos acceso.
Esta técnica es muy útil para la administración de servidores remotos, es habitual cuando tenemos un servidor expuesto en internet, y tenemos el puerto ssh abierto para poder acceder y administrarlo, encontrar en los logs del servidor intentos de acceso. Se puede establecer un sistema de clave pública/privada para estar más seguros, pero en los logs siguen apareciendo intentos de conexión, ya que el puerto sigue abierto, vamos a eliminar estos intentos de acceso usando esta técnica.
Se puede simplificar todo el proceso mediante el programa knockd, un servidor port-knock, la descripción del programa dice lo siguiente:
A port-knock server that listens to all traffic on a given network interface (only Ethernet and PPP are currently supported), looking for a special «knock» sequences of port-hits. A remote system makes these port-hits by sending a TCP (or UDP) packet to a port on the server. When the server detects a specific sequence of port-hits, it runs a command defined in its configuration file. This can be used to open up holes in a firewall for quick access.
Como dice en la descripción este programa cuando detecta la secuencia de puertos ejecuta el comando que le indiquemos, esta es la gran diferencia de realizar este proceso con iptables, lo que nos brinda una gran flexiblidad. Este demonio escucha a nivel de la capa de enlace, por lo que es capaz de atender las peticiones aunque halla un firewall bloqueando los puertos.
Está incluido en el repositorio oficial de debian por lo que es muy fácil instalarlo:
root@servidor~# aptitude install knockd
Tenemos que editar el fichero /etc/default/knockd para habilitarlo y configurar el interfaz de red en la que escucha.
START_KNOCKD=1
# command line options
KNOCKD_OPTS=»-i eth0″
A continuación tenemos que editar el fichero /etc/knockd.conf para configurarlo, por defecto esta es su apariencia:
[options]
UseSyslog[openSSH]
sequence = 7000,8000,9000
seq_timeout = 5
command = /sbin/iptables -A INPUT -s %IP% -p tcp –dport 22 -j ACCEPT
tcpflags = syn[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp –dport 22 -j ACCEPT
tcpflags = syn
Como se puede observar establece una secuencia de 3 puertos y un timeout de 5 segundos, después de los 5 segundos descarta todo, cuando recibe esa secuencia abre el puerto 22 con iptables.
Con 3 puertos (el rango de puertos es de 1-65535), tenemos 655353 = 281.462.092.005.375 combinaciones posibles, por lo que lo hace invulnerable ante un ataque por fuerza bruta, además, después de averiguar la secuencia tendrían que seguir escaneando para ver que puerto se ha abierto y por si fuera poco encontrar el password.
Es conveniente no poner los puertos en orden ascendente o descendente, ya que esto nos hace vulnerables a un posible escaneo, además si somos un poco paranoicos podemos indicarle más de 3 puertos. Este sería un ejemplo de configuración para que nos levante el servidor ssh al recibir la secuencia de entrada y nos lo deshabilite al recibir la secuencia de salida.
[options]
UseSyslog[openSSH]
sequence = 7000,3000,55000,1500
seq_timeout = 5
command = /etc/init.d/ssh start
tcpflags = syn[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 5
command = /etc/init.d/ssh stop
tcpflags = syn
Al instalar knockd también se instala el cliente para llamar al servidor, su uso sería el siguiente:
root@servidor~# knock 192.168.150.100 7000 3000 55000 1500
De esta forma establecemos la conexión y se levanta el servidor ssh (abrimos la puerta).
Entramos por ssh y realizamos las operaciones necesarias, una vez salimos no debemos olvidarnos de realizar la secuencia para cerrar la puerta.
root@servidor~# knock 192.168.150.100 9000 8000 7000
Así cerramos la puerta. Si ahora intentamos acceder por ssh nos rechazará la conexión.
Esto es lo que nos deja en los logs del servidor, donde podemos observar como efectivamente realiza las acciones indicadas.
Nov 25 22:12:37 servidor knockd: 192.168.150.135: openSSH: Stage 1 Nov 25 22:12:37 servidor knockd: 192.168.150.135: openSSH: Stage 2 Nov 25 22:12:37 servidor knockd: 192.168.150.135: openSSH: Stage 3 Nov 25 22:12:37 servidor knockd: 192.168.150.135: openSSH: Stage 4 Nov 25 22:12:37 servidor knockd: 192.168.150.135: openSSH: OPEN SESAME Nov 25 22:12:37 servidor knockd: openSSH: running command: /etc/init.d/ssh start Nov 25 22:13:59 servidor knockd: 192.168.150.135: closeSSH: Stage 1 Nov 25 22:13:59 servidor knockd: 192.168.150.135: closeSSH: Stage 2 Nov 25 22:13:59 servidor knockd: 192.168.150.135: closeSSH: Stage 3 Nov 25 22:13:59 servidor knockd: 192.168.150.135: closeSSH: OPEN SESAME Nov 25 22:13:59 servidor knockd: closeSSH: running command: /etc/init.d/ssh stop
En el wiki de debian hay más información sobre qué es port knocking y cómo funciona.
4rjfpb
Gracias Richi.
Perdona por no contestar antes, pero como sabes estoy bastante liado.
Intentaré seguir por estos derroteros, si realmente te gusta y no quieres perderte ni un artículo puedes suscribirte al rss o a las newsletter. Y por supuesto, si lo consideras útil puedes difundirlo a tus redes sociales 😉
Saludos.
Joer Rafa, eres un crack.
Me encanta el blog, sigue así.