Port Knocking sin complicaciones

mié, 06 nov 2013 by Foron

(Así, pecando de básico desde el principio)

Históricamente, desde el punto de vista de la seguridad, los servidores han venido teniendo dos tipos de puertos:

  • Los que tienen que estar siempre abiertos: Los puertos HTTP o HTTPS de un servidor web, sin ir más lejos.
  • Los que sólo tienen que estar abiertos para unas IPs determinadas: SSH, por ejemplo.

La configuración, en ambos casos, siempre ha sido razonablemente sencilla; al menos si asumimos que, a menudo, el rango de IPs con acceso a esos puertos restringidos era conocido (oficinas, etc).

Con el tiempo, sobre los firewalls y todas sus variantes se han añadido otra serie de medidas "complementarias", que muchos no considerarán parte de la seguridad informática "de verdad", pero que han demostrado ser útiles si se usan adecuadamente y como parte de una solución más global. Me refiero, por ejemplo, al uso de librerías como TCPWrappers o de geolocalización, a los propios mecanismos de cada aplicación, o al uso de puertos no estándar para los servicios (los sandboxes por aplicación basados en la virtualización, Selinux y todo este tipo de medidas quedan fuera de este post).

Sin embargo, en la actualidad nos encontramos ante un problema añadido que no hemos tenido hasta la fecha: Las IPs origen que se tienen que conectar a esos servicios restringidos ya no son "tan estáticas" como antes. ¿Cómo abro el acceso SSH a un móvil? ¿Y el webmail corporativo? ¿Y el acceso IMAP?

Muchos diréis que nada como una buena VPN para solucionar este problemilla; y tendréis razón, claro. Ahora bien, el mundo de las redes privadas, por si sólo, tiene otra serie de problemas que no vamos a tratar aquí: ¿Qué tecnología VPN usamos? ¿Qué aplicación cliente? ¿A qué IPs permitimos establecer la conexión? ¿Dónde terminamos la red? ¿Qué acceso tiene un usuario de VPN una vez ha pasado ese terminador? En fin, lo dicho, todo un mundo.

En este post casi voy a limitarme a citar una herramienta más que usar a la hora de securizar un servidor: El Port Knocking. Ojo, se trata de un mecanismo adicional, y no de la solución definitiva a los problemas; pero sí es cierto que viene a ayudar con el problema del dinamismo actual de los orígenes.

El concepto general es realmente sencillo. El firewall del servidor mantiene bloqueado el puerto al que se quiere acceder, y sólo se habilita a través del envío de una secuencia determinada de paquetes. Las opciones son múltiples, y van desde simples SYN, en orden, a n puertos, hasta combinaciones más elaboradas, en las que se activan otros flags en las cabeceras.

A partir de esta idea básica, han ido apareciendo otras mejoras que vamos a ver en un minuto.

Port Knocking básico

La versión más sencilla del "protocolo" se basa, como vengo diciendo, en mandar una secuencia concreta de paquetes a varios puertos. Para su implementación en el lado del servidor, tenemos tres opciones. La primera requiere instalar software (knockd por ejemplo), y las otras dos usan únicamente iptables.

Si optáis por la vía de knockd, os tendréis que descargar el software (obviamente). Según la distribución que uséis, esto será más o menos fácil, así que no me voy a meter con la instalación.

[options]
  logfile = /var/log/knockd.log

[IMAPon]
  sequence    = 6030,6026,6031
  seq_timeout = 5
  command     = /sbin/iptables -I INPUT 2 -s %IP% -p tcp --dport 993 -j ACCEPT
  tcpflags    = syn

[IMAPoff]
  sequence    = 6040,6036,6041
  seq_timeout = 5
  command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 993 -j ACCEPT
  tcpflags    = syn

Esta es una configuración tipo, en mi caso de "/etc/knockd.conf". Como podéis suponer, cuando alguien envíe tres paquetes SYN a los puertos 6030,6026 y 6031, en ese orden, se ejecutará el comando definido en "command". En este ejemplo, es una simple regla iptables que permite que desde la IP origen se pueda conectar al puerto IMAP (IMAPon). Como la aplicación da la opción de lanzar más secuencias, se puede crear otra para eliminar la regla (IMAPoff).

Y poco más. En vuestro caso, tendréis que adaptar la regla iptables a vuestra configuración, o incluso podríais lanzar scripts más complejos, que por ejemplo manden un correo o alerta cada vez que se active el acceso.

Esta es la forma más simple de implementar el Port Knocking. Tiene fallos, como por ejemplo que un cambio de IP en el móvil supondría que la IP antigua tendría acceso permanente (o hasta eliminarla a mano), pero creo que son fáciles de solucionar (el match "recent" de iptables por ejemplo ofrece alternativas). Vosotros deberéis decidir si esto os sirve, o si necesitáis algo más elaborado.

La segunda forma de implementar esta versión original de Port Knocking es a través de iptables, sin software adicional. El proceso está muy bien documentado en el siempre magnífico wiki de archlinux, así que podéis seguir desde allí si optáis por esta vía.

Y para terminar, si queréis una alternativa específica de iptables, hay un módulo en xtables addons pensado para hacer Port Knocking. Se llama xt_pknock, y permite hacer cosas como esta (entre otras que veremos más adelante):

  iptables -A INPUT -p tcp -m pknock --knockports 4002,4001,4004 --strict --name IMAP --time 10 --autoclose 60 --dport 993 -j ACCEPT

El problema es que, hasta la fecha, os va a costar encontrar un kernel que traiga el módulo compilado, así que lo tendríais que hacer vosotros.

Port Knocking con autenticación

Aunque obligar a que el origen conozca la secuencia concreta que enviar al servidor sea útil, no es menos cierto que tiene margen de mejora. La más obvia va en el sentido de verificar que la conexión procede realmente desde un usuario autenticado.

Sobre esta idea, Michael Rash (autor, entre otros, de psad) implementó una mejora del Port Knocking sobre el concepto de Single Packet Authorization (SPA): fwknop. El objetivo es el mismo (abrir un puerto a través de iptables si usamos Linux), pero usando para ello un único paquete UDP con unos datos determinados. De esta manera, se evitan los problemas generados a partir del envío de múltiples paquetes (llegar desordenados, bloqueo por IDS, ...) y, además, da la opción de cifrar el payload con un algoritmo que también ofrezca autenticación. Podéis ver el listado de features y las ventajas de esta implementación en la propia web de fwknop.

La instalación de fwknopd es muy sencilla. De hecho, está disponible en muchas distribuciones. Como no podía ser de otra forma, tener muchas más funcionalidades también hace que la configuración sea algo más complicada que en el caso de knockd, aunque sigue siendo manejable.

Este es el momento en el que debería escribir algunas notas y ejemplos de configuración pero, la verdad, visto que en la web ya hay un buen tutorial, prefiero no alargar mucho más el post. Si tenéis alguna duda, escribid un comentario e intentaré resolverla. Tened en cuenta que fwknop es un proyecto "vivo", y que por lo tanto va mejorando con cada release. Las últimas versiones (a partir de la 2.5), por ejemplo, incluyen soporte para HMAC + SHA, de tal manera que se puede combinar con AES o GnuPG para mejorar la autenticación. Yo personalmente no he usado esta versión, así que no puedo comentar nada sobre esta nueva funcionalidad.

Una instalación tipo de fwknop, al menos en versiones anteriores a a la 2.5, usa dos ficheros de configuración. Cada parámetro está muy bien documentado, así que lo mejor es ir siguiendo los comentarios que veréis en fwknopd.conf y en access.conf. El primero se usa para definir si queremos poner el interfaz en modo promiscuo, el puerto en el que escucharemos los paquetes y, sobre todo, las cadenas de iptables que usaremos para incluir las reglas. Access.conf se usa para la parte más directamente relacionada con el acceso; empezando por todo lo relacionado con las claves de cifrado, y siguiendo con el contenido que puede ir en cada paquete, desde usuarios autorizados a puertos para los que se puede pedir acceso, pasando por un mecanismo de control de la IP origen desde la que se genera la solicitud.

Por último, y dejando a un lado fwknop, el módulo de Netfilter del que os he hablado antes, xt_pknock, también ofrece una versión de Port Knocking que ofrece SPA, de tal manera que se pueden escribir cosas como estas:

  ...
  iptables -A INPUT -p udp -m state --state NEW -m pknock --knockports 2000 --name IMAP --opensecret your_opensecret --closesecret your_closesecret -j DROP
  iptables -A INPUT -p tcp -m state --state NEW -m pknock --checkip --name IMAP -m tcp --dport 143 -j ACCEPT
  ...

Aún así, como os he dicho, este módulo todavía no es "demasiado fácil" de usar y, en todo caso, es más simple que lo que ofrece fwknop.

Clientes

La pregunta es: ¿Cómo se genera la secuencia que abre la puerta?

Si usamos la versión básica de Port Knocking, no hay ningún problema. Podemos usar la aplicación cliente del software (knock), o podemos usar nmap, nping, netcat, o cualquier otra aplicación que permita mandar paquetes con el flag SYN activo a un puerto concreto. Para móviles, también hay variedad; en android, por ejemplo, una búsqueda de "port knocking" da al menos dos aplicaciones gratuitas (y que funcionan, al menos en mi teléfono y tablet).

Si optamos por la versión con SPA, también tenemos aplicaciones para todo tipo de dispositivos y clientes, aunque en este caso tendremos que tirar, probablemente, por las aplicaciones creadas específicamente para fwknop. Yo personalmente no he probado las versiones para móvil, así que poco puedo aportar. En el tutorial tenéis los enlaces y sus limitaciones (sobre todo relacionadas con el uso de HMAC). Por supuesto, si estáis en Linux, no tendréis problema para usar el propio software cliente que trae fwknop.

Notas

No pretendo empezar una discusión sobre si el Port Knocking es útil o no, o de si entra dentro de lo llamado "Security through obscurity"; pero sí tengo claro que es una herramienta más, y que es perfectamente "usable" en muchos entornos. Ahora bien, aunque podamos estar de acuerdo en que el Port Knocking básico es algo limitado, la implementación de fwknop sí que es, indudablemente, mucho más completa desde el punto de vista de la seguridad informática.


Comments