31 may 2013

Seguridad mediante ocultación de puertos con Port knocking

Port knocking

Buenas tardes, hoy vengo a hablaros de la técnica conocida como "Port knocking" que según la Wikipedia:

El golpeo de puertos (del inglés port knocking) es un mecanismo para abrir puertos externamente en un firewall mediante una secuencia preestablecida de intentos de conexión a puertos que se encuentran cerrados. Una vez que el firewall recibe una secuencia de conexión correcta, sus reglas son modificadas para permitir al host que realizó los intentos conectarse a un puerto específico.

Cómo vemos es una técnica de las conocidas como "seguridad mediante ocultación" que como su palabra bien dice, se trata de ocultar ciertos elementos a usuarios no legítimos para que estos "no puedan verlos". Es lo mismo que cuándo  en redes wifi se oculta el ESSID para que nuestros vecinos "no puedan ver nuestra red". Eso en teoría, en la práctica las cosas son diferentes, ya que hay formas más que conocidas para ver redes ocultas, en el caso de las redes wifi y hay formas de saber cuáles son los puertos que hay que llamar para "activar" ese servicio oculto, aunque eso no lo veremos en este artículo.

Aquí veremos solamente, como configurar port knocking para abrir un puerto en concreto de forma que nos permita acceder al mismo momentaneamente hasta que volvamos a cerrarlo. Al contrario de como se puede leer en el artículo de la Wikipedia "sus reglas son modificadas para permitir al host que realizó los intentos conectarse a un puerto específico"; nosotros no tendremos en cuenta el host que realiza la llamada si no que simplemente abriremos el puerto para todos y lo cerraremos también para todos.

Concretamente veremos como mediante la llamada a una serie de puertos se abrirá el acceso al servicio SSH para que podamos conectar al host remoto, y una vez terminado veremos como cerrar de nuevo ese puerto. La gestión de apertura y "cerrado" de puertos será llevada a cabo por "iptables" el cortafuegos por defecto en gran cantidad de distribuciones Linux, la mayoría. Por lo que lo primero de todo es bloquear el acceso SSH al servidor con iptables, ya que si no este artículo no tendría sentido.

Para bloquear el puerto, en el servidor como superusuario hacemos lo siguiente:

#iptables -A INPUT -p tcp –dport 22 -j DROP

Esto lo que hace es indicar a iptables que añada (A) una nueva regla a la cadena de entrada (INPUT) para el protocolo tcp (-p tcp), en la que descarte (-j DROP) todos los paquetes recibidos al puerto de destino 22 (–dport 22), que es el puerto SSH por defecto.

Aprovecho para mencionar que no entraremos en más detalles que los necesarios con lo relativo a iptables, hay mucha y muy buena documentación por toda la red.

Podemos continuar.

En el servidor también tenemos que instalar y configurar el servicio que se encargará de escuchar los "golpes en los puertos" y procederá a ejecutar la sentencia que le hayamos indicado.

El servicio se llama "knockd" y está en casi todos los repositorios de la gran mayoría de distribuciones, sino, puedes descargarlo desde su página y compilarlo por ti mismo. Incluye tanto el servidor como el cliente así que lo instalaríamos en ambos equipos si el cliente también es Linux. Si tu equipo no es Linux puedes buscar por la red clientes para "Port knocking" que los hay para todas las plataformas.

Una vez instalado el servicio vamos a configurarlo para ello editamos como superusuario el fichero /etc/knockd.conf, que por defecto ya trae unas sentencias para abrir y cerrar el puerto SSH aunque vamos a cambiarlas:

Lo dejaremos como se muestra a continuación:

[openSSH]sequence       = 5000,7000,6000seq_timeout  = 5command      = /sbin/iptables -D INPUT -p tcp –dport 22 -j DROPtcpflags           = syn[closeSSH]sequence       = 6000,8000,7000seq_timeout  = 5command      = /sbin/iptables -A INPUT -p tcp –dport 22 -j DROPtcpflags           = syn

La primera sentencia "openSSH" espera la secuencia de llamada a los puertos 5000, 7000 y 6000, cuándo eso puertos sean "tocados" ejecutará el comando /sbin/iptables -D INPUT -p tcp –dport 22 -j DROP, que elimina la sentencia creada en iptables encargada de bloquear el puerto SSH, permitiéndonos así poder conectar. Mientras que la sentencia "closeSSH" hace lo contrario, la vuelve a añadir para que los paquetes que lleguen al puerto SSH sean descartados.

Una vez hecho esto tenemos que habilitar el demonio "knockd" para que funcione como servicio, si no no podremos arrancarlo. Para ello modificamos el fichero /etc/default/knockd y cambiamos, también como superusuario el mandato:

START_KNOCKD=0

Poniéndole un 1 para marcarlo como activo:

START_KNOCKD=1

Una vez hecho esto ya podemos arrancar el servicio mediante /etc/init.d/knockd start o service knockd start si estás en una distribución basada en Debian, o con la propia de tu distribución.

El servidor está listo para escuchar los "golpeos" de puertos, ahora desde el equipo cliente ejecutamos (la dirección del servidor para este artículo es 192.168.1.29, debes sustituirla por el tuyo):

$knock -v 192.168.1.29 5000:tcp 7000:tcp 6000:tcp

La marca "-v" le indica que lo haga en modo "verbose" (que muestre lo que va haciendo), seguido de la dirección IP del servidor (192.168.1.29), seguido de los puertos a "tocar" en cuestión en el orden indicado, poniendo el protocolo utilizado para realizar el "toque" separado por dos puntos ":"

Si lo hemos hecho bien seremos capaces de conectar al servidor a partir de este momento por SSH.

Para volver a cerrar el puerto una vez terminemos de usar la conexión SSH haremos lo mismo pero llamando a los puertos indicados para ese propósito:

$knock -v 192.168.1.29 6000:tcp 8000:tcp 7000:tcp

A partir de este momento las conexiones al servidor SSH serán filtradas hasta que volvamos a permitirlas.

Como vemos, esta es una buena forma de tener un puerto abierto pero "oculto" a llamadas de usuarios ilegítimos con lo que ganamos un poco de "seguridad" en nuestros servicios. Pero como dije al principio no es infalible y por tanto no significa que nuestro servicio se vuelva impenetrable.

Para terminar vamos a ver como esta técnica sirve para muchas más cosas que para abrir o cerrar puertos. La podemos usar para todo lo que se nos ocurra, por ejemplo podríamos detener o arrancar el servicio SSH en vez de abrir o cerrar sus puertos, podemos realizar una actualización del sistema de forma remota sin ni siquiera tener que acceder al sistema, podemos añadir o eliminar un usuario, podemos mover ficheros de lugar, podemos eliminar ciertos ficheros, cualquier cosa, siempre con cuidado y teniendo en mente lo dicho de que esta no es una técnica infalible.

Vamos a ver como hacemos para crear un fichero (vacío en este caso) en el escritorio de cierto usuario. Para ello añadimos una nueva regla en el fichero /etc/knockd.conf:

[createFile]sequence         = 9000,8000,9500seq_timeout    = 5command        = touch /home/tecnogame/Escritorio/FicheroCreadotcpflags             = syn

Tras reiniciar el servicio "knockd", cuando llamemos a los puertos indicados se creará en el Escritorio del usuario "tecnogame" el fichero vacío con nombre "FicheroCreado":

$knock -v 192.168.1.29 9000:tcp 8000:tcp 9500:tcp

Cabe mencionar que el fichero se creará con permisos de superusuario ya que es el usuario encargado de ejecutar el servicio knockd. Ese es uno de los motivos por los que hay que tener mucho cuidado con el uso de esta técnica. ya que si ponemos una sentencia para eliminar un usuario y alguien descubre cuáles son los puertos a los que hay que llamar, pues ya sabemos lo que pasará. Por tanto mejor usarlo para cosas "triviales" y que no impliquen mucho riesgo en nuestros servidores.

Eso ha sido todo por hoy, cualquier duda o comentario puedes dejarlo abajo.

Puedes seguir todo el proceso en video si lo prefieres:

[youtube UhKpx5qPtz0 nolink]

5 comentarios:

  1. Tengo una duda, si el servidor está "detrás" del típico rourter ADSL, al hacer el "toc, toc" sería este quien recibiese la señal, con lo que creo que habría que redirigir los puertos del router más el ssh hacia el servidor. ¿Es correcto?Un saludo

    ResponderEliminar
  2. Sí, así es. Pero hay que tener en cuenta que así haciendo un escaneo de puertos se verán cuáles son los puertos que hay que tocar para abrir el servicio (siempre que el atacante sepa que usas port knocking). Por lo que estando detrás de un router ADSL o abres un rango de puertos que incluya a los que hay que tocar para que no sea tan descarado o mejor casi dejarlo sin port knocking, ya que abrir un rango de puertos conllevaría otros riesgos. La verdad no se cuál sería la forma óptima.Saludos

    ResponderEliminar
  3. [...] El viernes Dolphin nos trajo su post: Seguridad mediante ocultación de puertos con Port knocking. [...]

    ResponderEliminar
  4. Gracias por tu respuesta, pero si redirijo varios puertos del router hacia el servidor y este no contesta al no tener un servicio en funcionamiento en dichos puertos, el escaneo no detectaría puertas abiertos ¿estoy equivocado?

    ResponderEliminar
  5. No, estás en lo cierto, error mío. No deberían verse los puertos al no tener un servicio escuchando.Saludos

    ResponderEliminar