La connexion fonctionne, PWD fonctionne, puis LIST se bloque jusqu’à ce que le client abandonne ou passe dans un autre mode de données. Cette séparation est la signature : la connexion de contrôle vers le port 21 est saine, alors que la connexion de données se construit depuis une adresse ou un port que l’autre côté ne peut pas atteindre. Derrière une passerelle VPN qui fait aussi du NAT, le coupable habituel est une commande FTP dont la charge utile nomme une adresse de tunnel comme 10.8.0.6. La traduction des en-têtes ne touche jamais cette valeur.

Ce qui suit, c’est d’où vient cette valeur et quelle boîte a le droit de la changer.

Ce qui casse, c’est la charge utile, pas le tunnel

FTP place le point de terminaison de données à l’intérieur du flux de contrôle. En mode actif, le client envoie PORT avec sa propre adresse et son port, et le serveur rappelle ce couple. En mode passif, le serveur répond 227 avec un couple, et le client rappelle celui-là à la place.

Les deux formes portent le même type d’énoncé : connecte-toi à cette adresse, sur ce port. Un appareil qui ne réécrit que les en-têtes IP et TCP laisse l’énoncé intact, si bien qu’un côté continue d’essayer d’atteindre une adresse qui n’existe que de l’autre côté d’un tunnel. La connexion de données se bloque après que la connexion de contrôle a déjà été déclarée saine.

Trois modes, trois charges utiles

Le tableau ci-dessous montre à quel côté il est demandé d’appeler, et ce qu’un NAT qui ne réécrit que les en-têtes peut y faire.

Lisez la dernière colonne comme ce qui échoue en premier. En mode actif, c’est le serveur qui appelle une adresse privée ; en mode passif, c’est le client ; avec FTPS, la charge utile est du texte chiffré et la boîte intermédiaire a encore moins de matière.

ModeValue in the control streamWho dials whomHeader-only NAT leaves
Active (PORT)client address and portserver dials the clienta server dialing an unreachable tunnel address
Passive (227)server address and portclient dials the servera client dialing an address it cannot route to
FTPSthe same values, inside TLSas aboveciphertext, so no rewrite happens at all

Placez l’auxiliaire là où la traduction se produit

Sous Linux, la réécriture de la charge utile est faite par l’auxiliaire nf_conntrack_ftp. Il surveille la connexion de contrôle, apprend le port négocié, crée une attente pour le flux de données et, sur une boîte NAT, réécrit l’adresse et le port à l’intérieur de la charge utile. Il n’aide que sur l’appareil qui traduit l’adresse du client. Le charger sur le client, ou sur un routeur qui ne fait que transmettre le flux, ne change rien à la session.

Ces trois commandes montrent si le module est présent, s’il est rattaché et si une attente existe pendant qu’une session est ouverte :

modprobe nf_conntrack_ftp
lsmod | grep nf_conntrack_ftp
conntrack -L expect | grep ftp

Charger le module n’est pas la même chose que le rattacher. Les noyaux à partir de 4.7 sont livrés avec net.netfilter.nf_conntrack_helper=0, donc l’auxiliaire attend une règle explicite, par exemple iptables -t raw -A PREROUTING -p tcp --dport 21 -j CT --helper ftp. Si la liste d’attentes reste vide pendant qu’un transfert est tenté, c’est le rattachement qu’il faut vérifier, pas le module.

Mode passif : dites au serveur quoi annoncer

Le mode passif est plus facile à rendre déterministe parce qu’on peut dire au serveur quoi mettre dans la réponse 227. Dans vsftpd, c’est pasv_address, avec pasv_min_port et pasv_max_port ; ProFTPD utilise MasqueradeAddress et PassivePorts. Réglez-les d’abord, car une adresse annoncée correcte supprime le besoin de réécrire quoi que ce soit de ce côté.

Laissez ensuite passer exactement cette plage de ports par la passerelle, par exemple -A FORWARD -i tun0 -p tcp --dport 30000:30100 -j ACCEPT, pour que la règle corresponde à ce que le serveur annonce.

Les deux réglages doivent concorder. Un serveur à qui l’on dit d’annoncer 30000-30100 alors que la passerelle autorise 40000-40100 échoue de la façon la moins utile : la conversation de contrôle paraît saine et chaque connexion de données meurt. Comparez les nombres avant de déboguer quoi que ce soit d’autre.

Deux signatures de panne, et ce que FTPS supprime

Un blocage sur LIST désigne la première connexion de données de la session, là où la réécriture d’adresse et l’attente doivent toutes deux fonctionner. Un blocage sur RETR après un LIST qui fonctionne désigne le transfert lui-même, c’est-à-dire la plage passive ou le MTU du tunnel. Cette seconde signature n’est pas un problème de charge utile, et les réglages de l’auxiliaire ne la corrigeront pas.

FTP sur TLS supprime la charge utile que lit l’auxiliaire. Une boîte intermédiaire ne peut pas réécrire une valeur PORT ou PASV qu’elle ne peut pas déchiffrer, donc il reste un mandataire qui termine TLS, un serveur qui annonce une adresse joignable dans une plage bornée, ou un autre protocole de transfert.

Un court ordre de vérifications

Travaillez du symptôme vers l’extérieur. Confirmez que LIST échoue alors que PWD réussit, capturez l’adresse dans la charge utile PORT ou 227, et demandez quel appareil traduit cette adresse. Rattachez-y l’auxiliaire, surveillez la liste d’attentes pendant un transfert, puis corrigez le mode passif sur le serveur et reflétez la plage dans la règle de la passerelle.

Gardez la panne du chemin de données séparée de la panne de transfert massif, car elles vous mènent à des réglages différents.

Articles similaires