Derrière un routeur NAT

Architecture du montage

Notre architecture devient un peu plus compliquée puisque :

  • le client FTP est derrière un routeur NAT ;
  • le serveur lui aussi se trouve derrière un routeur NAT.

Ce qui nous donne :

Architecture NAT/NAT

Côté client

Sur la passerelle du client (GNU/Linux avec iptables), nous avons chargé les modules nf-conntrack-ftp et nf-nat-ftp, nécessaires pour que le client puisse utiliser le mode actif.

Notons que dans un cas de figure comme celui-ci, si nous comptons sur le suivi de connexion pour résoudre nos problèmes de connexions RELATED, celui-ci sera mis en œuvre :

  • pour le mode passif côté serveur ;
  • pour le mode actif côté client.

En nous souvenant de ce qui a déjà été vu à propos du suivi de connexion en FTPES, nous pouvons prévoir une impasse…

Côté serveur

Dans cette configuration, l'adresse IP(v4) du serveur sera une adresse privée. Or de l'extérieur, la seule adresse accessible sera l'IP publique attribuée par le fournisseur d'accès.

La première idée qui vient à l'esprit est donc de rediriger en DNAT le port 21 du routeur sur l'adresse IP du serveur.

iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 21 -j DNAT --to-destination 192.168.10.76

DNAT du port 21 Pouvons-nous prévoir le comportement ? Une requête arrivant sur xxx.yyy.zzz.ttt port 21 va être redirigée sur notre serveur. Il répondra à la requête. Côté canal de contrôle, il ne devrait pas y avoir de problèmes.

Mode actif

Dans ce mode, où le client FTP devient serveur pour les DATA, le serveur ne devrait pas poser de problèmes, s'il reçoit l'adresse IP publique du routeur NAT du client. S'il y a un problème, il faudra donc chercher à le résoudre du côté du client, mais avec les modules de suivi de connexion du protocole FTP de Netfilter, nous avons nos chances.

Essai en FTP

Si nous utilisons le mode actif, le client enverra son adresse et un port pour que pure-ftpd puisse ouvrir une connexion TCP et ça devrait fonctionner. Vérifions dans le compte-rendu de FileZilla :

Statut :	Connexion à 82.243.80.13:21...
...
Commande :	OPTS UTF8 ON
Réponse :	200 OK, UTF-8 enabled
Statut :	Connecté
Statut :	Récupération du contenu du dossier...
Commande :	PWD
Réponse :	257 "/" is your current location
Commande :	TYPE I
Réponse :	200 TYPE is now 8-bit binary
Commande :	PORT 192,168,0,16,204,129
Réponse :	200 PORT command successful
Commande :	MLSD
Réponse :	150 Connecting to port 52353
Réponse :	226-Options: -a -l 
Réponse :	226 7 matches total
Statut :	Succès de la lecture du contenu du dossier
Le client, en mode actif envoie son adresse IP privée et pourtant, tout fonctionne. Miracle ? Comment la passerelle côté serveur peut-elle interpréter une adresse IP privée qu'il ne sait pas router ?

Sniffons sur la passerelle du serveur (Tshark, la version en ligne de commande de Wireshark est notre ami)…

...
     19 0.386311    82.229.41.132         82.243.80.13          FTP      Request: TYPE I
     20 0.386608    82.243.80.13          82.229.41.132         FTP      Response: 200 TYPE is now 8-bit binary
     21 0.435339    82.229.41.132         82.243.80.13          FTP      Request: PORT 82,229,41,132,143,22
     22 0.435765    82.243.80.13          82.229.41.132         FTP      Response: 200 PORT command successful
...
     25 0.522738    82.243.80.13          82.229.41.132         FTP      Response: 150 Connecting to port 36630
Ce que l'on voit passer ici n'est plus l'adresse IP privée du client, mais l'adresse publique de sa passerelle.

Il est fort ce netfilter

Il est fort, certes, mais i ne fait pas de miracles. Les modules nf-conntrack-ftp et surtout nf-nat-ftp dans le cas présent peuvent analyser et modifier le contenu des datagrammes FTP parce qu'ils ne sont pas chiffrés.

Essai en FTPES

Est-ce bien la peine ? Netfilter ne pourra pas faire son travail sur du FTP chiffré. Essayez si vous ne me croyez pas. Vous obtiendrez dans le FileZilla un message du type :

Commande :	PORT 192,168,0,16,186,176
Réponse :	500 I won't open a connection to 192.168.0.16 (only to 82.229.41.132)

82.229.41.132, c'est ici l'adresse publique du routeur du client.

Même message que si les modules nf-conntrack-ftp et nf-nat-ftp n'étaient pas chargés sur le routeur NAT du client, soit dit en passant.

Existe-t-il un contournement ? Rien de propre. Sauf si j'ai raté quelque chose, nous devrons nous passer du mode actif en FTPES dans cette topologie.

Le mode passif

Nous avons déjà vu ce qu'il se passe côté serveur. Sur le routeur NAT du serveur, il faudra donc aussi rediriger les ports que nous avons spécifié dans la configuration de pure-ftpd :

iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 65525:65535 -j DNAT --to-destination 192.168.10.76

Cette solution sera acceptable dans la mesure où il n'y a qu'un seul serveur FTP derrière le NAT.

Essai en FTP

Ici, nous risquons de rencontrer un problème du fait que dans ce mode, le serveur va présenter son adresse IP qui est ici privée donc, non routée. FileZilla sait contourner cette erreur, mais nous allons lui dire de ne pas le faire : Filezilla passif sans intelligence Ce qui nous permettra de mettre en évidence cette erreur :

Commande :	PASV
Réponse :	227 Entering Passive Mode (192,168,10,76,255,251)
Statut :	Le serveur a envoyé une réponse passive avec une adresse non routable. Échec du mode passif.
Erreur :	Échec lors de la récupération du contenu du dossier
Comment corriger cette erreur ? Il y a deux façons de faire, dont une que nous avons déjà rencontrée côté client pour le mode actif :

Netfilter, au secours !

En chargeant les modules nf-conntrack-ftp et nf-nat-ftp, nous avons nos chances :

Commande :	PASV
Réponse :	227 Entering Passive Mode (82,243,80,13,255,245)
Commande :	MLSD
Réponse :	150 Accepted data connection
Réponse :	226-Options: -a -l 
Réponse :	226 6 matches total
Statut :	Succès de la lecture du contenu du dossier
Et ça fonctionne. Le conntrack corrige à la volée. C'est bien, surtout si le routeur NAT du serveur récupère une adresse IP publique qui change dans le temps, mais il est clair qu'en mode FTPES, ceci ne fonctionnera plus.

Dans pure-ftpd

Il est parfaitement possible de demander à pure-ftpd d'exposer l'adresse IP publique de sa passerelle, lorsqu'il travaille en mode passif. Cette solution ne sera acceptable que si cette passerelle dispose d'une adresse IP publique fixe, bien entendu.

Nous modifions la ligne de commande comme suit (elle commence à devenir vraiment longue) dans /etc/inetd.conf :

ftp  stream tcp4 nowait root /usr/sbin/pure-ftpd -j -lpuredb:/etc/pure-ftpd/pureftpd.pdb -E -T:30 -c3 -C2 -Y1 -p 65525:65535 -P 82.243.80.13

Cette opération va perturber le fonctionnement du suivi de connexions FTP de Netfilter, aussi bien sur le serveur lui-même que sur son routeur NAT. Sur le routeur, ce n'est pas important puisque les ports réservés au mode passif sont déjà explicitement redirigés.

Sur le serveur lui-même, en revanche nous avons actuellement :

:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i eth1 -p tcp -m tcp --dport 22 -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 21 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 
Il nous faut maintenant ouvrir explicitement les ports 65525 à 65535 à cause du suivi de connexion rendu inopérant :

iptables -A INPUT -i eth1 -p tcp --dport 65525:65535 -j ACCEPT

Nous rechargeons la configuration de inetd et nous essayons :

Commande :	PASV
Réponse :	227 Entering Passive Mode (82,243,80,13,255,248)
Commande :	MLSD
Réponse :	150 Accepted data connection
Réponse :	226-Options: -a -l 
Réponse :	226 6 matches total
Statut :	Succès de la lecture du contenu du dossier
Tout va bien.

Essai en FTPES

Avec les modifications apportées aux règles iptables du côté du serveur, le suivi de connexion n'est plus nécessaire. Du côté du client, en mode passif, il n'y a pas besoin de suivi de connexion spécifique à FTP. Nous pouvons nous attendre à ce que tout fonctionne correctement :

Commande :	AUTH TLS
Réponse :	234 AUTH TLS OK.
...
Commande :	PASV
Réponse :	227 Entering Passive Mode (82,243,80,13,255,245)
Commande :	MLSD
Réponse :	150 Accepted data connection
Réponse :	226-Options: -a -l 
Réponse :	226 6 matches total
Statut :	Succès de la lecture du contenu du dossier
Pas de mauvaise surprise.

Bilan

Si nous donnons la priorité à l'usage du FTPES qui offre le chiffrement de la connexion, dans une telle topologie où le serveur comme les clients se trouvent derrière des routeurs NAT, la seule solution est de faire du FTP passif.

Bien entendu, en IPv6 tout devient plus simple puisqu'il n'y a plus de NAT nulle part. Un jour peut-être ?

En attendant résumons les configurations des divers protagonistes :

Serveur FTP

  • Les lignes de commande dans inetd (IPv4 et IPv6) :
    ftp  stream tcp4 nowait root /usr/sbin/pure-ftpd -j -lpuredb:/etc/pure-ftpd/pureftpd.pdb -E -T:30 -c3 -C2 -Y1 -p 65525:65535 -P 82.243.80.13
    ftp  stream tcp6 nowait root /usr/sbin/pure-ftpd -j -lpuredb:/etc/pure-ftpd/pureftpd.pdb -E -T:30 -c3 -C2 -Y1 -p 65525:65535
  • les règles Iptables :
    # iptables-save
    
    # Generated by iptables-save v1.4.8 on Sun Jan 29 11:46:57 2012
    *nat
    :PREROUTING ACCEPT [1255:400710]
    :POSTROUTING ACCEPT [715:52251]
    :OUTPUT ACCEPT [715:52251]
    COMMIT
    # Completed on Sun Jan 29 11:46:57 2012
    # Generated by iptables-save v1.4.8 on Sun Jan 29 11:46:57 2012
    *filter
    :INPUT DROP [400:95800]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [884:74191]
    -A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT 
    -A INPUT -i lo -j ACCEPT 
    -A INPUT -p tcp -m tcp --dport 21 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT 
    -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 
    -A INPUT -i eth0 -p tcp -m tcp --dport 65525:65535 -j ACCEPT 
    COMMIT

    Le suivi de connexion est resté en place pour permettre la connexion en mode FTP actif (sans chiffrement) ;

  • les modules chargés pour le suivi de connexion FTP :
    # lsmod | grep ftp
    
    nf_conntrack_ftp        5505  0 
    nf_conntrack           46311  6 iptable_nat,nf_nat,nf_conntrack_ipv4,xt_state,xt_conntrack,nf_conntrack_ftp

Routeur NAT du FTP

  • les règles Iptables relatives au fonctionnement du FTP :
    # iptables-save
    
    # Generated by iptables-save v1.4.8 on Sun Jan 29 11:56:26 2012
    *nat
    :PREROUTING ACCEPT [3838277:231166320]
    :POSTROUTING ACCEPT [916200:55004844]
    :OUTPUT ACCEPT [47781:3326346]
    ...
    -A PREROUTING -i eth0 -p tcp -m tcp --dport 21 -j DNAT --to-destination 192.168.10.76 
    -A PREROUTING -i eth0 -p tcp -m tcp --dport 65525:65535 -j DNAT --to-destination 192.168.10.76 
    -A POSTROUTING -o eth0 -j MASQUERADE 
    COMMIT
    ...
  • les modules de suivi de connexion ne sont pas nécessaires pour ce qui nous intéresse ici, compte tenu des règles Iptables mises en place. Il peut cependant être utile de les charger si par ailleurs des clients du même réseau souhaitent faire du FTP actif sur l'internet :
    # lsmod | grep ftp
    
    nf_nat_ftp              1999  0 
    nf_conntrack_ftp        5505  1 nf_nat_ftp
    nf_nat                 13276  3 nf_nat_ftp,ipt_MASQUERADE,iptable_nat
    nf_conntrack           46327  7 nf_nat_ftp,nf_conntrack_ftp,ipt_MASQUERADE,iptable_nat,nf_nat,nf_conntrack_ipv4,xt_state

Routeur NAT des clients

Il n'y a rien de spécial, à part optionnellement charger les modules de suivi de connexion nf-conntrack-ftp et nf-nat-ftp pour autoriser le FTP actif, aussi bien sur notre serveur que sur d'autres, situés quelque part sur l'internet.

Nous supposons que par ailleurs, Iptables configure correctement la passerelle pour autoriser les connexions RELATED et ESTABLISHED venant de l'internet dans le routage NAT.

Rappel important

Souvenons-nous que les modules de suivi de connexion nf-conntrack-ftp et nf-nat-ftp sont dans l'incapacité totale de faire leur travail en présence d'un flux chiffré (FTPES). La conséquence principale est que même si le serveur FTP est installé directement sur une passerelle et peut donc être atteint sans DNAT, le client derrière un routeur NAT n'aura pas de possibilité d'y accéder en FTPES actif.

Une autre piste

Une solution intéressante, mais qui sort du cadre de cette étude sur FTP consiste à établir un tunnel chiffré, par exemple entre la passerelle du réseau contenant le serveur FTP et le poste du client : Solution VPN Dans ce cas, le tunnel étant lui-même chiffré, rien n'interdirait d'abandonner FTPES au profit de FTP, ce qui simplifierait le problème. Dans une telle topologie, le client pourrait même à travers son tunnel accéder à tous les nœuds de son réseau privé. Une solution comme openvpn supporte très bien de passer un routeur NAT, encore faudra-t-il que les pare-feux laissent passer le tunnel. Mais tout ceci est une autre histoire .