Configurar Port Knocking para securizar el servicio SSH

Seguridad de puertos en Linux Ubuntu: securizando con Port Knocking.

Port Knocking (traducido al español como «golpeo de puertos») es una de las técnicas que se puede utilizar para securizar un servidor Linux. Su funcionamiento es muy sencillo y permitiría que solo personas autorizadas accedan a un determinado puerto.

Junto al uso de un servicio de cortafuegos por software, su principal función es evitar que los puertos queden expuestos, tanto a personas como a bots o escáneres automatizados de puertos.

El usuario llama a una serie de puertos en un orden, por ejemplo al 2023, 2000, 9999 y el servicio de knockd habilitaría una regla en el firewall del sistema para permitir a la dirección IP solicitante el acceso al puerto o los puertos que hayamos configurado.

Si te interesa esta funcionalidad, sigue leyendo hasta el final porque puede ser una de las guías más completas de Port Knocking con knockd.

Instalar y configurar knock en Linux

En primer lugar, instalamos el demonio knockd en nuestro servidor. En este caso, la instalación se está realizando sobre Ubuntu 20.04 y la versión del paquete es la 0.8.

Para instalarlo, ejecutamos: sudo apt install knockd

Knock tiene dos ficheros de configuración: /etc/default/knockd y /etc/knockd.conf, los explico a continuación.

Fichero /etc/default/knockd

El primero a editar será /etc/default/knockd donde estableceremos el parámetro START_KNOCKD con valor a 1 para habilitar el servicio y cambiaremos el nombre de la interfaz en el parámetro KNOCKD_OPTS por ens3, quedando de la siguiente manera:

El nombre de la interfaz de escucha podemos extraerlo con ifconfig, pudiendo así especificar qué tarjeta de red funcionará bajo esta técnica.

Fichero /etc/knockd.conf

Es el fichero donde se definen todas las reglas o secuencias de golpeo de puertos. Por defecto, vienen configuradas las dos secuencias que estamos interesados en configurar: apertura del puerto SSH y cierre del puerto SSH.

En primer lugar, en el apartado de [options] cambiaremos UseSyslog por logfile = /var/log/knockd.log para que sea más fácil depurar y auditar el funcionamiento de knock.

Luego, tanto en el apartado [openSSH] como en el [closeSSH] especificaremos en sequence los puertos por orden. Es recomendable que los puertos no sean consecutivos, ya que normalmente los escaneos de puertos realizados por bots se realizan de manera incremental.

El parámetro seq_timeout define el tiempo de espera máximo (expresado en segundos) para que se complete la secuencia. También se recomienda que este tiempo no sea muy alto, para evitar que ante un escaneo de puerto masivos se complete la secuencia.

Tras la personalización, el fichero queda configurado de la siguiente manera:

Recuerda reiniciar el servicio de knockd tras los cambios en los ficheros: /etc/init.d/knockd restart

Configurar knockd con UFW (especialmente Ubuntu)

En servidores Ubuntu, por defecto, el firewall activo es UFW (Uncomplicated Firewall). Este gestiona las reglas de iptables a través de una sintaxis más simple.

Si queremos que las reglas creadas por knock sean gestionadas con UFW, basta con cambiar el parámetro command. Esto daría como resultado el siguiente fichero:

Diagrama con explicación de cómo funciona el Port Knocking.

Conexión desde un cliente y depuración

Aunque podemos realizar el Port Knocking mediante telnet, lo recomendable es utilizar el cliente knock (apt install knock) por su sencillez. En nuestro ejemplo de uso, el comando para abrir el puerto 22 sería:
knock -d 300 servidor.evaristogz.com 2023 2000 9999

Como peculiaridad, el delay (parámetro -d) se expresa en milisegundos, mientras que en el fichero de configuración lo expresamos en segundos. Puedes usar -v para ver el modo verbose.

Crear una función bash para facilitarnos el acceso

En total debemos ejecutar tres comandos: el knock que crea la regla de acceso al puerto, el comando de conexión mediante SSH a ese servidor y el knock que ejecuta la secuencia closeSSH y elimina la regla de acceso.

Por ello, una buena opción para facilitarnos el acceso es crear una función bash y añadirla en nuestro .bashrc del equipo cliente:
function portk { knock -d 300 $2 2023 2000 9999; ssh -o TCPKeepAlive=yes -o ServerAliveInterval=15 $1@"$2"; knock -d 300 $2 9999 2000 2023; }

Posterior a añadir esta función, cargamos los cambios del fichero con source .bashrc.

Su uso sería el siguiente: portk NombreUsuarioSSH servidor.con.port.knocking.para.SSH

Depuración del funcionamiento de knock

En caso de que nos encontremos con problemas, podemos consultar el log /var/log/knockd.log.

En él ha de aparecer nuestra dirección IP, la secuencia que se está intentando llevar a cabo y un stage por cada puerto que tenemos configurado en sequence. Si el resultado es correcto, veremos «OPEN SESAME» y el comando ejecutado. Un ejemplo de caso de éxito sería el siguiente:
Configuración de Port Knocking con knockd en Linux Ubuntu.

También podemos revisar el syslog para ver si UFW o iptables está realizando algún bloqueo: tail -f /var/log/syslog | grep NuestraDirecciónIP

Ejemplos de otros casos de uso de knockd

En linux.die.net encontraremos otros tres ejemplos para aplicar Port Knocking en nuestros servidores. Sin embargo, extrapolando un poco más el uso de Port Knocking, se me ocurren otros usos «locos».

Estos pueden ser el abrir un puerto de administración o inseguro durante un determinado tiempo, reiniciar un servicio o ejecutar un script.

Está claro que no es para lo que está pensado, pero puede ser una ñapa solución para entornos de desarrollo, técnicos de nivel 1 sin acceso a servidores, redes internas… De la misma manera, es una forma de mostrar otras funcionalidades o configuraciones que permite knockd.

Una de las limitaciones que tiene knockd es que no permite diferenciar secuencias según la interfaz de red, por lo que no podríamos habilitar una secuencia para, por ejemplo, permitir abrir el puerto SSH únicamente por la interfaz de red interna.

Apertura temporal del puerto 80

start_command se usa para para ejecutar un comando tras la secuencia, que sería abrir el puerto 80 mediante iptables. cmd_timeout es el tiempo definido (expresado en segundos y que en este caso corresponde a 15 minutos) tras el que se ejecutará stop_command, que elimina la regla de iptables y nos garantiza que el puerto no se queda expuesto.

Reinicio de un servicio o ejecución de un script

En este ejemplo se muestra la combinación de dos secuencias distintas: una para reiniciar el servicio apache2 y otra para ejecutar un script bash con las instrucciones que deseemos. En el caso de la secuencia runScript, esta solo se podrá ejecutar una vez debido al parámetro one_time_sequences.

Referencias

Compartir es agradecer. Si te ha gustado... ¡compartélo!
Comparte con tus amigos










Enviar

2 Respuestas

  1. J.D dice:

    Hola, he estado repasando este software y veo que esta totalmente desfasado con bugs y problemas de seguridad segun los issues de github. Estoy buscando otra alternativa pero no veo nada. La estoy buscando porque no me funciona, se me queda en stage1 he probado con curl, nc, etc pero nada

    • Evaristo GZ dice:

      Hola J.D! Gracias por comentar.
      Es cierto, acabo de ver las issues del repositorio. Imagino que has probado incluso copiando las configuraciones de este post, ¿no?

      Si quieres, escríbeme un correo o por Telegram con más info e intento ayudarte.
      Saludos!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.