Le dilemne du ftp.

La F.A.Q d'OpenBSD à ce sujet est très intéressante, mais il se pose un certain nombre de problèmes pas toujours faciles à regler. On va donc voir les cas suivants:

  • Les clients FTP derrière un firewall PF avec NAT.
  • Serveur FTP protégé par un firewall PF local.
  • Serveur FTP dans une DMZ.
  • Client FTP protégé par un firewall PF local.

Ceci nous fournira une vue d'ensemble sur les points à connaitre pour gérer le FTP.

Notions:

FTP est un protocole TCP permettant le transfert de fichiers entre deux hôtes d'un réseau. Il fonctionne en deux modes: passif et actif. En mode passif, le client initie la connection et demande au serveur de se mettre en écoute sur un port aléatoire qu'il (le serveur) aura choisi et qu'il indiquera au client. En mode actif, le client choisit lui-même le port, et en informe le serveur. Dans le premier cas, le firewall est problématique car il filtre le traffic entrant. Dans le second, le NAT peut poser problème.

Clients FTP derrière un firewall PF avec NAT.

Pour qu'un client FTP puisse passer “à travers” un firewall en NAT, il faut utiliser un daemon qui joue le rôle de mandataire entre le client et le serveur. Ce daemon est apellé proxy. OpenBSD fournit en standard un proxy pour le FTP: ftp-proxy(8). Dans la plupart des cas, il suffit de le lancer par inetd(8) (à moins d'avoir un nombre important de connections FTP par jour). Insérez la ligne suivante dans votre fichier /etc/inetd.conf:

127.0.0.1:8021 stream tcp nowait root /usr/libexec/ftp-proxy ftp-proxy -m 49500 -M 50000

127.0.0.1:8021 indique qu'il faut créer un socket sur le port 8021 (port par défaut de ftp-proxy) sur l'interface loopback. -m 49500 définit le début de la plage de ports à utiliser et -M 50000 la fin. Vous pouvez choisit n'importe quelle plage de ports au delà des ports réservés, mais prenez soin de choisir une plage suffisament élevée pour ne pas interférer. Enregistrez les modifications, et rechargez inetd:

kill -HUP `cat /var/run/inetd.pid`

Ensuite, dans /etc/pf.conf, on crée une redirection. Afin que ce soit totalement transparent, tout le traffic provenant du réseau local de type FTP sera redirigé vers ftp-proxy.

rdr on $Internal_If inet proto tcp from $Internal_Net to any port ftp -> $Loopback port 8021

La redirection n'ouvrant pas de ports, il faut donc autoriser explicitement ceux-ci. Dans cette situation, nous avons deux choix:

* Ouvrir une plage de ports complète suivant nos choix pour ftp-proxy dans inetd.conf

  • Autoriser l'utilisateur proxy (utilisé par ftp-proxy pour “dropper” ses privilèges).

Dans le premier cas, on inscrit la ligne suivante dans /etc/pf.conf:

pass in on $External_If inet proto tcp from any to $External_If port 49500:50000 keep state

Dans le second (que je trouve plus élégant, puisque les ports ne sont ouverts qu'en cas de connection):

pass in on $External_If inet proto tcp from any to $External_If user proxy keep state

Relancez PF:

pfctl -f /etc/pf.conf

Et c'est fini.

Serveur FTP protégé par un firewall PF local.

Le serveur FTP d'OpenBSD utilise les ports supérieurs à 49152 par défaut (ce qui peut être restreind en consultant ftpd(8)). Il faut donc ouvrir cette plage et le port FTP pour que cela fonctionne.

pass in on $ext_if proto tcp from any to any port 21 keep state
pass in on $ext_if proto tcp from any to any port > 49151 keep state

Serveur FTP dans une DMZ.

Dans ce cas, il faut à la fois rediriger le traffic et l'autoriser. En utilisant à nouveau le serveur ftp d'OpenBSD, cela revient à rediriger et autoriser les ports 21 et 49152 à 65535.

ftp_server = "10.0.3.21"

rdr on $External_If proto tcp from any to any port 21 -> $ftp_server port 21
rdr on $External_If proto tcp from any to any port 49152:65535 -> $ftp_server port 49152:65535

# in on $External_If
pass in quick on $External_If proto tcp from any to $ftp_server port 21 keep state
pass in quick on $External_If proto tcp from any to $ftp_server port > 49151 keep state

# out on $Internal_If
pass out quick on $Internal_If proto tcp from any to $ftp_server port 21 keep state
pass out quick on $Internal_If proto tcp from any to $ftp_server port > 49151 keep state

Client FTP protégé par un firewall PF local.

Cette fois on se retrouve face à un problème, les connections sont initiés depuis la machine locale, qui s'accroche aux ports de l'interface externe. Que fait-on? on ouvre une plage de ports? un peu barbare. Je n'aime pas laisser un plage de ports ouverts en permanence. La solution élégante: wget. Si on consulte la page de manuel wget(1), on y lit:

     --bind-address=ADDRESS
     When making client TCP/IP connections, "bind()" to
     ADDRESS on the local machine.  ADDRESS may be speci-
     fied as a hostname or IP address.  This option can be
     useful if your machine is bound to multiple IPs.

Voilà qui est intéressant, on peut dire à wget de s'accrocher à une interface spécifique pour télécharger. Si on repense à ce qu'on disait pour les clients derrière un firewall NAT, l'idée devient intéressante. Toutes les connections passeraient par ftp-proxy. Ok, mais y a pas un moyen de rendre ceci transparent? Si, /etc/wgetrc, où on peut définir cette interface pour tout le monde: Maintenant, voyons un autre problème dans cette situation: comment faire pour les ports? certains MASTER_SITE forcent le FTP passif! En consultant la page de man de bsd.port.mk(5), il y est précisé que l'on peut définir un client autre que ftp(1):

FETCH_CMD     Command used to fetch distribution files for this port.
              Defaults to ftp(1).  User settings.  Can be used to go
              through excessively paranoid firewalls.

Voilà qui tombe bien! une petite ligne FETCH_CMD=wget dans mk.conf(5) et le tour est joué.

Conclusions.

J'éspère que cette doc est suffisement complète, le seul outil qui reste problématique pour moi est Midnight Commander, mais pour le reste, tout marche.

Crédits

Auteur Original : Eric DILLENSEGER
Mis Sur Le Wiki Par Azwaw OUSADOU
Date De Parrution : 20/07/2009

documentations/reseau/pf_ftp.txt · Dernière modification: 2009/07/20 18:29 par bsdmaniak
OpenBSD Apache Driven by DokuWiki
CC Attribution-Noncommercial-Share Alike 3.0 Unported