Esta pagina se ve mejor con JavaScript habilitado

Portknocking

 ·  🎃 kr0m

Como muchos de vosotros sabréis una conexión TCP no se considera establecida hasta que se han intercambiado una seria de paquetes, el archiconocido TCP-Handshake, este consta de un paquete inicial SYN otro de respuesta SYN/ACK y un último ACK, en ese momento se encarga de enviar información la aplicación bindeada a ese puerto.

Portknocking consiste en utilizar este tipo de tráfico para realizar ciertas operaciones en el equipo servidor, de este modo mediante una combinación de intentos de conexión podremos aplicar reglas de firewall o ejecutar cualquier otro comando.

Lo primero que haremos será instalar el servicio de portknocking en el servidor:

emerge -av net-misc/knock

Ahora realizamos la configuración según necesidades, en mi caso al enviar la combinación mágica 7000 8000 9000 permitiré el acceso por ssh insertando una regla de iptables para tal fin:

vi /etc/knockd.conf

[options]
        logfile = /var/log/knockd.log
[openSSH]
       sequence    = 7000,8000,9000
       seq_timeout = 5
       command     = /sbin/iptables -I INPUT 1 -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

Finalizamos la configuración indicando en que interfaz debe permanecer a la escucha knockd:

vi /etc/conf.d/knock

IFACE="eth0"
OPTS=""

Arrancamos el servicio y lo añadimos al arranque:

/etc/init.d/knock start
rc-update add knock default

Insertamos la ACL que se encargará de bloquear el tráfico ssh si no se ha enviado el portknock:

iptables -I INPUT 1 -p tcp –dport 22 -j DROP

Si tenemos las reglas por defecto para que bloqueen el tráfico debemos abrir los puertos utilizados por knockd ya que si no lo hacemos iptables que está a nivel de kernel interceptará el tráfico antes que knockd y será como si nunca se hubiese enviado el knock:

iptables -I INPUT 1 -p tcp –dport 7000 -j ACCEPT
iptables -I INPUT 1 -p tcp –dport 8000 -j ACCEPT
iptables -I INPUT 1 -p tcp –dport 9000 -j ACCEPT

Podemos ver los logs en /var/log/knockd.log:

tail -f /var/log/knockd.log

En la parte del cliente tendremos que instalar algún software capaz de generar el tráfico esperado por knockd, en mi caso netcat pero cualquier otro sería igualmente válido:

emerge -av net-analyzer/netcat

Generamos le tráfico esperado por knockd:

nc -z A.B.C.D 7000 8000 9000

En el servidor podemos ver como se ha aplicado la regla de firewall:

tail -f /var/log/knockd.log

[2014-10-30 16:46] E.F.G.H: openSSH: Stage 1
[2014-10-30 16:46] E.F.G.H: openSSH: Stage 1
[2014-10-30 16:46] E.F.G.H: openSSH: Stage 2
[2014-10-30 16:46] E.F.G.H: openSSH: Stage 3
[2014-10-30 16:46] E.F.G.H: openSSH: OPEN SESAME
[2014-10-30 16:46] openSSH: running command: /sbin/iptables -I INPUT 1 -s E.F.G.H -p tcp --dport 22 -j ACCEPT

Además si consultamos las reglas de iptables:

iptables -L -n

ACCEPT     tcp  --  E.F.G.H         0.0.0.0/0            tcp dpt:22

Cuando hayamos terminado de realizar las tareas administrativas podemos cerrar la brecha mediante:

nc -z A.B.C.D 9000 8000 7000

NOTA: Una posible forma de aumentar la seguridad de este sistema podría ser reconfigurando la combinación de puerto según la franja horaria o mediante un algoritmo propio, de este modo una combinación válida puede que deje de serlo en X tiempo.

No hay duda de que esta técnica puede resultar de mucha utilidad en entornos donde la paranoia prima sobre la funcionalidad, de este modo el servicio solo estaría expuesto un tiempo limitado para una ip origen en concreto ;)

Si te ha gustado el artículo puedes invitarme a un RedBull aquí