viernes, 11 de noviembre de 2011

Linux: Connection tracking with FTP and iptables



Uno de los problemas más comunes con que se puede encontrar un sysadmin utilizando iptables es a la hora de hacer el deployment de un servidor FTP (como por ejemplo vsftpd o proftpd) estando detrás de un  NAT. El cliente se podrá conectar al servidor, pero este no logrará realizar ninguna operación en el (como listar, o transferir archivos).

Según los distintos RFC que definen al protocolo FTP, este por regla general utiliza dos puertos, el TCP/20 para datos y el TCP/21 para control; Aunque esto no siempre es así y es lo que veremos en este post.
Para evitar el problema mencionado anteriormente, podemos decir que FTP trabaja en dos modos: el modo activo y el modo pasivo.

El modo activo:
  1. El cliente se conecta desde un puerto no privilegiado (N >1023) al puerto de control del servidor (21).
  2. El cliente comienza a escuchar el puerto N + 1.
  3. El servidor se conectará al puerto N + 1 desde su puerto de datos (TCP/20).
  4. El cliente responderá con un ACK al servidor.
El modo pasivo:
  1. El cliente abre dos puertos aleatorios ( N > 1023  y N + 1).
  2. El primer puerto (utilizado para control) se conecta al puerto 21 del servidor y envía el comando PASV.
  3. Luego el servidor abre un puerto no privilegiado ( P > 1023 ) y envía PORT P al cliente. 
  4. El cliente inicia una conexión desde el puerto N + 1 al puerto P del servidor para transferir datos.
Como notaran, hacer un seguimiento de los estados de las conexiones es una tarea complicada, si solamente queremos mantener abierto el puerto 21 para todas las conexiones entrantes, y no abrir rangos de puertos innecesarios podemos hacer uso del connection tracking de Netfilter.
Bien sabemos que las conexiones pueden tener diferentes estados (podemos verlo en la salida de netstat(1)):
  • NEW: Un cliente intentando establecer una nueva conexión.
  • ESTABLISHED: Una conexión ya establecida. 
  • RELATED: Una conexión haciendo un nuevo request pero que ya es parte de otra conexión establecida.
  • INVALID: Si no es ninguno de los tres estados anteriores, la conexión es invalida.
Desde kernels 2.4 connection_tracking es la habilidad que tiene Netfilter de mantener una tabla de estados de las distintas conexióes y así poder tener un track de como se encuentran estas.
Para poder hacer esto, debemos seguir algunos pasos que detallaré a continuación.
Primero que nada debemos añadir la regla de iptables necesaria para esto:
-A INPUT -m state --state NEW,ESTABLISHED,RELATED -m tcp --dport 21 -j ACCEPT
Para poder realizar el connection tracking y evitar incluir múltiples reglas de firewall que dejen abierto un gran rango de puertos, podemos hacerlo utilizando dos módulos del kernel: 
# modprobe nf_conntrack_ftp
Al incluir en el kernel nf_conntrack_ftp, por una cuestión de dependencias también será cargado nf_conntrack, el cual es el módulo del kernel responsable de proveer las funciones comunes de connection tracking a cada uno de los subsistemas que lo utilicen. A esto también podemos añadir esto de manera definitiva creando el archivo /etc/modprobe.d/conntrack.conf, con el siguiente contenido:
alias conntrack nf_conntrack
alias conntrack_ftp nf_conntrack_ftp
 
Si deseamos realizar el connection tracking utilizando FTP en un puerto no estándar, por ejemplo TCP/8021, primero se deberá hacer la excepción en las reglas de iptables, y luego pasarle al módulo nf_conntrack_ftp el parámetro ports, el cual toma un valor entero que define al número de puerto donde realizaremos esta acción, por ejemplo en el archivo /etc/modprobe.d/conntrack.conf esto quedaría así:
options nf_conntrack_ftp ports=8021

No hay comentarios:

Publicar un comentario