Por qué los listados FTP se cuelgan detrás de una puerta de enlace VPN que hace NAT
El inicio de sesión y PWD funcionan mientras LIST y RETR se atascan cuando el NAT solo reescribe las cabeceras. Vea dónde debe ir el auxiliar FTP y cómo arreglar el modo pasivo.
El inicio de sesión funciona, PWD funciona, y entonces LIST se cuelga hasta que el cliente se rinde o pasa a otro modo de datos. Esa división es la firma: la conexión de control al puerto 21 está sana, mientras que la conexión de datos se construye desde una dirección o un puerto que el otro extremo no puede alcanzar. Detrás de una puerta de enlace VPN que también hace NAT, el culpable habitual es un comando FTP cuya carga útil nombra una dirección de túnel como 10.8.0.6. La traducción de cabeceras nunca toca ese valor.
Lo que sigue es de dónde sale ese valor y qué caja tiene permiso para cambiarlo.
Lo que se rompe es la carga útil, no el túnel
FTP pone el extremo de datos dentro del flujo de control. En modo activo el cliente envía PORT con su propia dirección y puerto, y el servidor marca de vuelta a esa tupla. En modo pasivo el servidor responde 227 con una tupla, y el cliente marca esa en su lugar.
Ambas formas llevan el mismo tipo de afirmación: conéctate a esta dirección, en este puerto. Un dispositivo que solo reescribe cabeceras IP y TCP deja la afirmación intacta, así que un extremo sigue intentando alcanzar una dirección que solo existe al otro lado de un túnel. La conexión de datos se atasca después de que la conexión de control ya se haya declarado buena.
Tres modos, tres cargas útiles
La tabla siguiente muestra a qué lado se le dice que marque, y qué puede hacer un NAT que solo reescribe cabeceras al respecto.
Lea la última columna como lo que falla primero. En modo activo es el servidor quien marca a una dirección privada; en modo pasivo es el cliente; con FTPS la carga útil es texto cifrado y la caja intermedia tiene aún menos con qué trabajar.
| Mode | Value in the control stream | Who dials whom | Header-only NAT leaves |
|---|---|---|---|
| Active (PORT) | client address and port | server dials the client | a server dialing an unreachable tunnel address |
| Passive (227) | server address and port | client dials the server | a client dialing an address it cannot route to |
| FTPS | the same values, inside TLS | as above | ciphertext, so no rewrite happens at all |
Ponga el auxiliar donde ocurre la traducción
En Linux la reescritura de la carga útil la hace el auxiliar nf_conntrack_ftp. Vigila la conexión de control, aprende el puerto que se negoció, crea una expectativa para el flujo de datos y, en una caja NAT, reescribe la dirección y el puerto dentro de la carga útil. Solo ayuda en el dispositivo que traduce la dirección del cliente. Cargarlo en el cliente, o en un enrutador que solo reenvía el flujo, no cambia nada de la sesión.
Estos tres comandos muestran si el módulo está presente, si está enganchado y si existe una expectativa mientras hay una sesión abierta:
modprobe nf_conntrack_ftp
lsmod | grep nf_conntrack_ftp
conntrack -L expect | grep ftp
Cargar el módulo no es lo mismo que engancharlo. Los núcleos desde 4.7 en adelante vienen con net.netfilter.nf_conntrack_helper=0, así que el auxiliar espera una regla explícita, por ejemplo iptables -t raw -A PREROUTING -p tcp --dport 21 -j CT --helper ftp. Si la lista de expectativas sigue vacía mientras se intenta una transferencia, lo que hay que revisar es el enganche, no el módulo.
Modo pasivo: dígale al servidor qué anunciar
El modo pasivo es más fácil de hacer determinista porque se le puede decir al servidor qué poner en la respuesta 227. En vsftpd eso es pasv_address, junto con pasv_min_port y pasv_max_port; ProFTPD usa MasqueradeAddress y PassivePorts. Configure eso primero, ya que una dirección anunciada correcta elimina la necesidad de reescribir nada en ese lado.
Luego deje pasar exactamente ese rango de puertos por la puerta de enlace, por ejemplo -A FORWARD -i tun0 -p tcp --dport 30000:30100 -j ACCEPT, para que la regla coincida con lo que anuncia el servidor.
Los dos ajustes tienen que coincidir. Un servidor al que se le dice que anuncie 30000-30100 mientras la puerta de enlace permite 40000-40100 falla de la manera menos útil: la conversación de control parece sana y cada conexión de datos muere. Compare los números antes de depurar cualquier otra cosa.
Dos firmas de fallo, y qué elimina FTPS
Un cuelgue en LIST apunta a la primera conexión de datos de la sesión, donde tanto la reescritura de dirección como la expectativa tienen que funcionar. Un cuelgue en RETR después de un LIST que funciona apunta a la transferencia misma, es decir al rango pasivo o a la MTU del túnel. Esa segunda firma no es un problema de carga útil, y los ajustes del auxiliar no la arreglarán.
FTP sobre TLS elimina la carga útil que lee el auxiliar. Una caja intermedia no puede reescribir un valor PORT o PASV que no puede descifrar, así que quedan un proxy que termina TLS, un servidor que anuncia una dirección alcanzable dentro de un rango acotado, o un protocolo de transferencia distinto.
Un orden breve de comprobaciones
Trabaje del síntoma hacia fuera. Confirme que LIST falla mientras PWD tiene éxito, capture la dirección dentro de la carga útil PORT o 227, y pregunte qué dispositivo traduce esa dirección. Enganche el auxiliar ahí, observe la lista de expectativas durante una transferencia, luego arregle el modo pasivo en el servidor y refleje el rango en la regla de la puerta de enlace.
Mantenga el fallo de la ruta de datos separado del fallo de transferencia masiva, porque lo llevan a ajustes distintos.