Cuando conectamos a un servidor FTP, tenemos la opción de elegir dos modos de conexión:
- Modo activo: el cliente establece una conexión al servidor FTP a través del puerto TCP 21, una vez establecida se crea un canal de datos entre el puerto TCP 20 del servidor y un puerto aleatorio superior al 1024 en el cliente.
- Modo pasivo: el cliente también establece la conexión al servidor FTP a través del puerto TCP 21. Una vez establecida la conexión el servidor abre un puerto aleatorio (> 1024) al que se conectará el cliente.
Me tomo la libertad de adjuntar estos dos esquemas de la Wikipedia, que lo explican de forma más gráfica y amplia:
Entrando al tema de la entrada, si quisiéramos configurar IPTABLES para permitir conexiones FTP con modo pasivo, no es tan sencillo como hacerlo para el modo activo. El modo activo únicamente necesita tener abiertos los puertos TCP 20 para datos y 21 para establecer la conexión:
# iptables -I INPUT 3 -p tcp --dport 21 -j ACCEPT # iptables -I INPUT 4 -m state --state RELATED,ESTABLISHED -p tcp --dport 20 -j ACCEPT
Con estas dos reglas permitimos el acceso para cualquier tipo de conexión al puerto 21 y posteriormente las conexiones ya establecidas o relacionadas con destino el puerto 20 (datos FTP). Pero, ¿qué pasa con el modo pasivo? no conocemos cual es el puerto de datos. Está claro que el puerto 21 tcp sí que tendrá que estar abierto como en el modo activo:
# iptables -I INPUT 3 -p tcp --dport 21 -j ACCEPT
Con esta configuración podremos conectar al FTP, pero llegado el momento de transferir datos o incluso listar los ficheros del FTP recibiremos un timeout:
Status: Connected Status: Retrieving directory listing... Command: PWD Response: 257 "/" Command: TYPE I Response: 200 Switching to Binary mode. Command: PASV Response: 227 Entering Passive Mode (192,168,1,129,54,45). Command: LIST Error: Connection timed out Error: Failed to retrieve directory listing
Los servidores FTP normalmente permiten establecer un rango de puertos aleatorios a ser usados con el modo pasivo. Lo que tenemos que hacer es aceptar ese rango en iptables para conexiones ya establecidas y relacionadas, no es necesario aceptarlo para nuevas conexiones ya que el FTP nunca se va a conectar a ese puerto sin pasar antes por el 21. Si hubieramos configurado el rango 10000-10500 tcp en el servidor FTP añadiríamos esta regla:
# iptables -I INPUT 3 -m state --state ESTABLISHED,RELATED -p tcp --dport 10000:10500 -j ACCEPT
Pero esto no es todo, todavía necesitamos cargar un par de módulos de IPTABLES que sirven para seguir las conexiones FTP y llevar un control sobre ellas. Los módulos son nf_conntrack_ftp e ip_nat_ftp. El primer es necesario siempre y el segundo cuando se trabaja con NAT. En RHEL, CentOS y derivados los módulos se pueden cargar en el fichero /etc/sysconf/iptables-config:
# Load additional iptables modules (nat helpers) # Default: -none- # Space separated list of nat helpers (e.g. 'ip_nat_ftp ip_nat_irc'), which # are loaded after the firewall rules are applied. Options for the helpers are # stored in /etc/modprobe.conf. IPTABLES_MODULES="nf_conntrack_ftp ip_nat_ftp"
Una vez cargados, reiniciamos iptables para cargar los módulos y verificamos que han sido cargados con el comando lsmod:
# lsmod | grep ip
nf_conntrack_ipv4 7694 4 nf_nat nf_defrag_ipv4 1039 1 nf_conntrack_ipv4 iptable_filter 2173 1 ip_tables 9567 1 iptable_filter ipt_REJECT 1931 2 ip6t_REJECT 3987 2 nf_conntrack_ipv6 7207 2 nf_defrag_ipv6 9873 1 nf_conntrack_ipv6 nf_conntrack 65524 6 nf_nat_ftp,nf_nat,nf_conntrack_ftp,nf_conntrack_ipv4,nf_conntrack_ipv6,xt_state ip6table_filter 2245 1 ip6_tables 10867 1 ip6table_filter ipv6 264641 34 ip6t_REJECT,nf_conntrack_ipv6,nf_defrag_ipv6,cnic
Y ya tendremos nuestro firewall configurado para permitir FTP en modo pasivo.