Après quelques expérimentations sur la gestion du FTP client derrière une Freebox v5 en mode routeur, il s'avère que :
Étrangement
la lecture du code source de linux coïncide avec les observations expérimentales.
la Freebox laisse passer tel quel tout segment TCP du client vers le serveur FTP,
sauf si les données TCP commencent une suite de lettres qui est un préfixe de "PORT" ou de "EPTR" (insensible à la casse)
à l'exception de la toute première commande FTP, qui elle passe toujours directement.
C'est
dans la fonction help dans nf_conntrack_ftp.c :
369 /* Until there's been traffic both ways, don't look in packets. */
370 if (ctinfo != IP_CT_ESTABLISHED &&
371 ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
372 pr_debug("ftp: Conntrackinfo = %u\n", ctinfo);
373 return NF_ACCEPT;
374 }
Concernant les segment TCP envoyé par le PC derrière la Freebox contenant juste "p", "po", "por", "port", "e", "ep", "epr", "eprt" : ces segments ne sont pas transmis par la Freebox. En fait la Freebox attend d'avoir une commande PORT ou EPRT complète avant de la transmettre.
Les séquences reconnues sont définies par le tableau
search qui associe à chaque direction (client->serveur, serveur->client) un tableau de "motifs" de la forme : (texte, fonction de décodage)
La fonction
find_pattern teste si un segment TCP correspond à un motif donné :
254/* Return 1 for match, 0 for accept, -1 for partial. */
255 static int find_pattern(const char *data, size_t dlen,
256 const char *pattern, size_t plen,
257 char skip, char term,
258 unsigned int *numoff,
259 unsigned int *numlen,
260 struct nf_conntrack_man *cmd,
261 int (*getnum)(const char *, size_t,
262 struct nf_conntrack_man *, char))
La Freebox perd ces données incomplètes, ce qui provoque une retransmission TCP.
C'est toujours
dans la fonction help :
425 if (found == -1) {
426 /* We don't usually drop packets. After all, this is
427 connection tracking, not packet filtering.
428 However, it is necessary for accurate tracking in
429 this case. */
430 pr_debug("conntrack_ftp: partial %s %u+%u\n",
431 search[dir][i].pattern, ntohl(th->seq), datalen);
432 ret = NF_DROP;
433 goto out;
En entrant une commande PORT ou EPRT mal-formée avec telnet, on peut mettre en vrac l'entrée NAT, qui ne transmet plus rien, jusqu'à ce que le client abandonne (RST du client).
Si une commande mal-formée correspondant à un motif a été envoyée par le client, find_pattern va systématiquement renvoyer -1, et le paquet sera systématiquement DROPé.
Donc cette donnée sera encore retransmise par le client, et DROPée encore, donc il n'est plus possible d'avancer sur cette connexion TCP.
Tout cela est causé uniquement par le fonctionnement du système de suivi d'état des connexions (modules nf_conntrack*) et non par le NAT lui-même, même si c'est le NAT qui rend indispensable le suivi d'état des connexions.
Edit : C'est mon 800ème message!