Port-Knocking y Single Packet Authorization

Son dos protocolos para securizar un servidor, ambos monitorizan el log de intentos de acceso a los puertos del servidor y actúan en consecuencia. Se basan en una política de log and drop, en la cual los puertos de un servidor están filtrados en vez de abiertos.

Esta aproximación es una barrera más que se pone ante un posible atacante, porque si se descubre una nueva vulnerabilidad en uno de los servicios, como por ejemplo SSH, te da igual tener fail2ban que te van a entrar. Por ello, es mejor tener por defecto todos los puertos cerrados y solo abrir los necesarios para las personas necesarias.

Además te evitas todos los escaneos que llegan cada hora a tu máquina.

Michael Rash en 2004 lanzó fwknop bajo la licencia GPL. Fue la primera implementación de port knocking que combina port-knocking cifrado con fingerprinting pasivo del SO.

Port-knocking

En este protocolo el servidor loguea los intentos de conexión de un cliente en ciertos puertos, si este intenta acceder según una secuencia predeterminada abre a esa IP otro puerto determinado durante una ventana de tiempo.

Limitaciones del Port knocking

Los problemas que presenta el protocolo de port-knocking son los siguientes:

  • Es difícil parar ataques replay de atacantes que pueden monitorizar las secuencias de port-knocking.
  • El límite de tamaño de transmisión de información determina el tipo de información que se puede enviar e incluso los sistemas criptográficos que se puedan usar.
  • Cualquier IDS entre cliente y servidor puede detectar una secuencia de port-knocking e interpretarla como un escaneo.
  • Es muy fácil realizar un ataque Dos contra un servidor protegido por port-knocking

Single Packet Authorization

En 2005 lanzó el modo Single Packet Authorization, que combina el filtro de paquetes log and drop con un sniffer pasivo de manera similar al port-knocking.

En vez de guardar la información de autenticación en los headers del paquete, SPA utiliza el payload que dado a que el MTU es mucho mayor permite almacenar más información. Gracias a este aumento de tamaño se consigue resolver los problemas del protocolo port-knocking:

  • SPA resuelve el problema del replay attack introduciendo datos random en el payload. Cada paquete está construido con formato determinado. Este incluye espacio para meter estos datos, una vez está el paquete, se cifra. De tal manera que la probabilidad de que haya dos paquetes idénticos es despreciable, incluso si llevan la misma información. Además el server va guardando los hash MD5 de los paquetes descifrados para automáticamente descartarlos si se recibe otro igual.

  • SPA resuelve el problema de transmisión de datos se resuelve usando el payload del paquete IP, de manera similar a como TCP encapsula datos de la capa aplicación. Esta implementación facilita el uso de sistemas criptográficos asimétricos. De hecho se puede construir hasta un canal de comandos sobre SPA.

  • SPA resuelve el problema de la falsa detección de IDS como escaneo enviando un solo paquete, además como el payload está cifrado, el IDS o cualquier sniffer por el camino solo verá un blob ininteligible de datos.

  • SPA resuelve el problema del tipo de Dos que rompe el port-knocking ya que un atacante no puede romper el protocolo mediante el spoofing de paquetes al servidor. Aunque todo sistema que analice paquetes sobre la red puede sufrir Dos por flood, pero no es una vulnerabilidad del protocolo SPA.

Limitaciones del Port knocking

Existen una serie de limitaciones que hay que tener en cuenta a la hora de aplicar el protocolo

Piggy-Backing en direcciones NAT

Los filtros de paquetes son buenos filtrando el tráfico de la capa transporte para abajo, pero no son buenos interpretando la capa aplicación. Por ello el criterio usado por el daemon para aceptar una conexión entrante después de recibir un paquete valido se limita a la IP, protocolo y puerto. Por ello si la IP autorizada es la externa de un NAT, cualquier equipo conectado en la misma red interna podría acceder en la ventana de tiempo de acceso.

HTTP y sesiones cortas

Cuando un daemon SPA agrega una regla temporal para permitir el acceso a una conexión TCP, se genera una ventana de tiempo suficiente para realizar la negociación TCP, sin embargo, las sesiones SSH suelen durar más de la ventana de acceso (generalmente 30s). Una vez pasado ese tiempo el puerto vuelve a cerrarse pero las conexiones establecidas se siguen permitiendo. Esta solución funciona bien para aplicaciones que utilizan sesiones TCP largas, pero las conexiones cortas como HTTP requerirían que cada vez que pase el tiempo de ventana se tuviese que volver a mandar otro paquete SPA para volver a abrir el puerto. Esto tiene dos soluciones, o se aumenta el tiempo de la ventana (con lo que se empeora la seguridad del protocolo) o se integra en la herramienta que debe acceder al puerto.

En general no es buena idea aplicar SPA para estas aplicaciones

Formato SPA

Todo paquete SPA contiene la siguiente información antes de ser cifrado:

  • Random data: 16 bytes, el grado de aleatoriedad es el que aporta la función rand() de Perl.
  • Usuario: El nombre del usuario que ejecuta el comando fwknop, el servidor lo utiliza para autorizar el uso o no de los puertos (al haberse descifrado el paquete anteriormente se asume que el proceso de autenticación se ha completado)
  • Timestamp: El timestamp del sistema local. El servidor lo utiliza para ver si entra dentro de la ventana de acceso, por ello es importante que todas las máquinas estén medianamente sincronizadas (NTP)
  • Versión del cliente fwknop
  • Modo commando: si el cliente quiere correr un comando o no.
  • Directiva de acceso: Un string que define qué IP, puertos y protocolos habilitar. El server antes de abrirlos comprueba que dicho usuario puede acceder a lo que solicita.
  • Comandos: si se ha habilitado el comando que se quiere ejecutar, por ejemplo /etc/init.d/apache2 restart
  • Hash del paquete: Hash md5 del paquete para verificación (aunque el descifrado sería suficiente)
  • Método de autenticación del server: Opcionalmente se puede exigir algún parámetro adicional de autenticación.

Uso

Una vez que tanto cliente como servidor están configurados, el cliente genera el paquete, transforma en Base64 cada uno de los campos y los concatena con :, posteriormente se cifra con el algoritmo seleccionado, Rijndael si se ha elegido criptografía simétrica o GnuPG si se ha elegido asimétrica. Una vez esta cifrado se vuelve a cifrar simétricamente con HMAC.

A continuación se envía al servidor, por defecto al puerto 62201 en UDP, el servidor lo loguea y decide si abrir o no el puerto.

FAQ

¿Porqué usar HMAC después de GnuPG?

La complejidad del código para descifrar GnuPG es infinitamente mayor que la de HMAC, por ello es más probable que tenga bugs. Cualquier paquete que entre se verifica primero con HMAC y si pasa el primer filtro ya se expone al código de descifrado de GnuPG

¿Se puede usar con Tor?

Si, por defecto fwknopd escucha en UDP, pero tor solo tira en TCP. Por ello, existe la posibilidad de que fwknopd levante un servicio TCP exclusivo para recibir paquetes. Al activarse ya se puede utilizar a través de Tor

¿Porqué utilizar claves GnuPG sin protección de contraseña en el servidor?

Las claves son seguras criptograficamente, sin embargo, en un servidor si quieres proteger las claves con contraseña, en algún sitio tienes que guardar la contraseña en texto plano. Por ello, no se aumenta la seguridad para nada.

Instalación

La version de Debian 7 es muy antigua así que a manita, aunque la de Debian 8 es la 2.6.0 que es aceptable.

Por lo que si tienes Debian 8:

Para el cliente apt-get install fwknop-client

Para el servidor apt-get install fwknop-server

Para Debian 7 o cualquier distro que no esté al día, se compila.

apt-get install gcc make        # -.-
apt-get install libpcap-dev

Seguir el tutorial http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html

Configuración

Generación de claves

Si se decide usar GnuPG hay que generar las claves si no se tienen. No pueden ser las claves de cliente y servidor de 4096, por lo que crearemos la del servidor de 2048.

gpg --gen-key

Se sigue el proceso y se pone una password. Al terminar vamos a editar la clave para quitarle la password

gpg --edit 
gpg> passwd
gpg> save

Cuando pida la contraseña ponerla vacía, y aunque te avise que estás vendiendo tu alma seguir adelante.

A continuación en cada maquina exportamos la clave pública

gpg -a --export  > key.asc

Importamos y firmamos la del servidor en el cliente y viceversa

gpg --import key.asc
gpg --edit-key 
gpg> sign
...
gpg> save

Configurar el daemon

Modificar los siguientes archivos en el servidor

# /etc/conf.d/fwknop
rc_need="net."
# /etc/fwknop/fwknop.conf 
PCAP_INTF ;

## Con tor
ENABLE_TCP_SERVER Y; 
TCPSERV_PORT 62202;
# /etc/fwknop/access.conf
## Acceso
SOURCE ANY; 
OPEN_PORTS tcp/22; 
REQUIRE_USERNAME lyz;

## Con tor
PCAP_FILTER tcp port 62202;

## Sin tor
PCAP_FILTER udp port 62201;

## GnuPG
GPG_HOME_DIR /root/.gnupg; 
GPG_DECRYPT_ID ; 
GPG_REMOTE_ID ; 
GPG_ALLOW_NO_PW Y; 
GPG_REQUIRE_SIG Y; 
GPG_IGNORE_SIG_VERIFY_ERROR N

Agregar las claves HMAC

Ejecutando el siguiente comando se guarda la configuración inicial en el cliente y se generan las clases HMAC.

fwknop -A tcp/22 -a   -D  --key-gen --use-hmac --server-port= --server-proto= --gpg-home-dir= --gpg-recipient= --gpg-signer-key= -U  --save-rc-stanza -n 

Copiar de ~/.fwknoprc las claves HMAC en la configuracion de acceso en el servidor

Sincronizar los dispositivos con ntp

apt-get install ntpdate
ntpdate se.pool.ntp.org

Modificar el init script

No se porqué pero el init script de Debian no tira bien, hay que comentar la siguiente línea en /etc/init.d/fwknop-server:

# [ "$START_DAEMON" = "yes" ] || exit 1

Configurar Iptables

Crear el archivo iptables.rules con la siguiente información (cada uno que la adapte a sus necesidades) y substituyendo por vuestra interfaz

# /etc/network/iptables.rules

*filter

# Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT 
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

# Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allows all outbound traffic
# You could modify this to only allow certain traffic
# -A OUTPUT -j ACCEPT

# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
# -A INPUT -p tcp --dport 80 -j ACCEPT
# -A INPUT -p tcp --dport 443 -j ACCEPT
# -A INPUT -p tcp --dport 62202 -j ACCEPT

# LOG fwknopd port
-A INPUT -p udp --dport 62201 -j LOG

# Allows SSH connections
# The --dport number is the same as in /etc/ssh/sshd_config
-A INPUT -i  -p tcp --dport 22 -j DROP 
-A INPUT -i  -p tcp --dport 22 -m state --state ESTABLISHED,RELATED -j ACCEPT

# Now you should read up on iptables rules and consider whether ssh access
# for everyone is really desired. Most likely you will only allow access from certain IPs.
# Allow ping
# note that blocking other types of icmp packets is considered a bad idea by some
# remove -m icmp --icmp-type 8 from this line to allow all kinds of icmp:
# https://security.stackexchange.com/questions/22711
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# log iptables denied calls (access via 'dmesg' command)
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy:
-A INPUT -j DROP 
-A FORWARD -j DROP

COMMIT

Para hacer que se cargue por defecto al reiniciar la máquina crear el siguiente script:

# /etc/network/if-pre-up.d/iptables
# !/bin/sh
/sbin/iptables-restore < /etc/network/iptables.rules

Y darle permisos chmod +x /etc/network/if-pre-up.d/iptables

src

  • Linux Firewalls de Michael Rash
  • http://www.cipherdyne.org/fwknop/docs
  • https://wiki.debian.org/iptables
Compartir

6 Comentarios

  1. Gran articulo, no me termina de convencer las limitaciones, pero necesito leer mas para sacar una opinión mas clara.
    Muchas gracias por realizar artículos de este nivel ;)

Deja una respuesta a rubio Cancelar respuesta

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax