Notre architecture devient un peu plus compliquée puisque :
Ce qui nous donne :
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 :
En nous souvenant de ce qui a déjà été vu à propos du suivi de connexion en FTPES, nous pouvons prévoir une impasse…
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
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.
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.
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 dossierLe 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.
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.
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.
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 :
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 :
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.
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 ACCEPTIl 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 dossierTout va bien.
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 dossierPas de mauvaise surprise.
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 :
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
# 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) ;
# 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
# 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 ...
# 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
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.
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 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 :
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 .