                                Ponts filtrants

  Alex Dupre

   <ale@FreeBSD.org>

   Version: 43126

   FreeBSD is a registered trademark of the FreeBSD Foundation.

   3Com and HomeConnect are registered trademarks of 3Com Corporation.

   Intel, Celeron, EtherExpress, i386, i486, Itanium, Pentium, and Xeon are
   trademarks or registered trademarks of Intel Corporation or its
   subsidiaries in the United States and other countries.

   Many of the designations used by manufacturers and sellers to distinguish
   their products are claimed as trademarks. Where those designations appear
   in this document, and the FreeBSD Project was aware of the trademark
   claim, the designations have been followed by the << (TM) >> or the
   << (R) >> symbol.

   2013-11-07 par gabor.
   Resume

   Souvent il est utile de diviser un reseau physique (comme un reseau
   Ethernet) en deux segments separes sans avoir `a creer des sous-reseaux,
   et utiliser de routeur pour les relier ensemble. Le dispositif qui
   connecte les deux reseaux de cette maniere est appele un pont. Un systeme
   FreeBSD avec deux cartes reseau est suffisant pour jouer le role d'un
   pont.

   Un pont fonctionne en scannant les adresses au niveau MAC (adresses
   Ethernet) des cartes connectees `a chacune de ses interfaces reseau et
   puis transfere le trafic entre les deux reseaux si la source et la
   destination sont situees sur un segment different. Sous beaucoup de points
   de vue un pont est similaire `a un commutateur (switch) Ethernet avec
   uniquement deux ports.

   Version franc,aise de Marc Fonvieille <blackend@FreeBSD.org>.

     ----------------------------------------------------------------------

   Table des matieres

   1. Pourquoi utiliser un pont filtrant?

   2. Comment l'installer

   3. Derniere preparation

   4. Activer le pont

   5. Configurer le coupe-feu

   6. Participants

1. Pourquoi utiliser un pont filtrant?

   De plus en plus frequemment, grace `a la baisse des couts des connexions
   Internet haut debit (xDSL) et aussi en raison de la reduction des adresses
   IPv4 disponibles, beaucoup de compagnies sont connectees `a l'Internet 24
   heures sur 24 et avec peu (parfois meme pas une puissance de 2) d'adresses
   IP. Dans ces situations il est souvent desirable d'avoir un coupe-feu qui
   filtre le trafic entrant et sortant depuis et vers l'Internet, mais la
   solution d'un filtrage de paquet base sur un routeur peut ne pas etre
   applicable, soit en raison de problemes de sous-reseau, le routeur
   appartient au fournisseur d'acces (ISP), ou parce qu'il ne supporte pas
   une telle fonction. Dans ces scenarios l'utilisation d'un pont filtrant
   est fortement conseillee.

   Un coupe-feu base sur un pont peut etre configure et insere entre le
   routeur xDSL et votre concentrateur/commutateur Ethernet sans aucun
   probleme d'adresse d'IP.

2. Comment l'installer

   Ajouter les fonctions de pont `a un systeme FreeBSD n'est pas difficile.
   Depuis la 4.5-RELEASE il est possible de charger de telles fonctionnalites
   sous forme de module au lieu d'avoir `a recompiler le noyau, simplifiant
   enormement la procedure. Dans les sous-sections suivantes j'expliquerai
   les deux methodes d'installation.

  Important:

   Ne pas suivre les deux methodes: une procedure exclue l'autre. Choisissez
   la meilleure en fonction de vos besoins et capacites.

   Avant d'aller plus loin, soyez sur de disposer deux cartes Ethernet qui
   supportent le mode promiscuous pour la reception et la transmission, comme
   elles doivent etre capables d'envoyer des paquets Ethernet avec n'importe
   quelle adresse, et non pas juste pour la leur. De plus, pour avoir de
   bonnes performances, les cartes devront etre capable controler le bus PCI
   (PCI bus mastering). Les meilleurs choix sont toujours l'Intel
   EtherExpress(TM) Pro, suivie de la serie 3c9xx de chez 3Com(R). Pour
   simplifier la configuration il peut etre utile d'avoir deux cartes de
   differents constructeurs (utilisant un pilote de peripherique different)
   afin de distinguer clairement quelle interface est connectee au routeur et
   quelle autre est connectee au reseau.

  2.1. Configuration du noyau

   Donc vous avez decide d'utiliser la bonne vieille methode d'installation.
   Pour commencer, vous devez ajouter les lignes suivantes `a votre fichier
   de configuration du noyau:

 options BRIDGE
 options IPFIREWALL
 options IPFIREWALL_VERBOSE

   La premiere ligne est pour compiler le support du pont, la seconde est le
   coupe-feu et la troisieme sont les fonctions de traces du coupe-feu.

   Maintenant il est necessaire de compiler et d'installer le nouveau noyau.
   Vous pourrez trouver des instructions detaillees dans la section Compiler
   et installer un noyau sur mesures du Manuel de FreeBSD.

  2.2. Le chargement de modules

   Si vous avez choisi d'employer cette methode nouvelle et plus simple; la
   seule chose `a faire maintenant est d'ajouter la ligne suivante au fichier
   /boot/loader.conf:

 bridge_load="YES"

   De cette fac,on, durant le demarrage du systeme le module bridge.ko sera
   charge avec le noyau. Il n'est pas necessaire de rajouter une ligne pour
   le module ipfw.ko, etant donne qu'il sera charge automatiquement apres
   l'execution des etapes presentees dans la section suivante.

3. Derniere preparation

   Avant de redemarrer afin de charger le nouveau noyau ou les modules
   necessaires (selon la methode d'installation precedemment retenue), vous
   devez faire quelques modifications dans le fichier de configuration
   /etc/rc.conf. La regle de defaut du coupe-feu est de rejeter tous les
   paquets IP. Au depart nous configurerons un coupe-feu "ouvert", afin de
   verifier son fonctionnement sans probleme relatif au filtrage de paquet
   (dans le cas ou vous faite cela `a distance, une telle configuration vous
   evitera de rester isole du reseau). Ajoutez les lignes suivantes dans
   /etc/rc.conf:

 firewall_enable="YES"
 firewall_type="open"
 firewall_quiet="YES"
 firewall_logging="YES"

   La premiere ligne activera le coupe-feu (et chargera le module ipfw.ko
   s'il n'est pas compile dans le noyau), la seconde le configurera dans le
   mode "ouvert" (comme explique dans /etc/rc.firewall), la troisieme ligne
   rendra le chargement des regles silencieux (sans affichage) et la
   quatrieme activera le support de trace d'activite du coupe-feu.

   Au sujet de la configuration des interfaces reseau, la methode la plus
   utilisee est d'assigner une adresse IP `a une seule des cartes reseau,
   mais le pont fonctionnera `a l'identique si les deux interfaces ou aucune
   n'ont d'adresse IP configuree. Dans le dernier cas (sans adresse IP) la
   machine faisant office de pont sera toujours cachee et inaccessible depuis
   le reseau: pour la configurer, vous devez vous attacher depuis la console
   ou `a travers une troisieme interface reseau separee du pont. Parfois,
   durant le demarrage du systeme, certains programmes ont besoin d'acceder
   au reseau, par exemple pour la resolution de noms: dans ce cas il est
   necessaire d'assigner une adresse IP `a l'interface externe (celle
   connectee `a l'Internet ou le serveur DNS reside), puisque le pont sera
   active `a la fin de la procedure de demarrage. Cela signifie que
   l'interface fxp0 (dans notre cas) doit etre mentionnee dans la section
   concernant ifconfig du fichier /etc/rc.conf, mais pas xl0. Assigner une
   adresse IP aux deux cartes reseau n'a pas beaucoup de sens, `a moins que,
   durant la procedure de demarrage, des applications devront acceder `a des
   services sur les deux segments Ethernet.

   Il y a une autre chose importante `a savoir. Quand on utilise l'IP sur
   Ethernet, il y a en fait deux protocoles Ethernet utilises: l'un est l'IP,
   l'autre est l'ARP. ARP effectue la conversion de l'adresse IP d'un hote en
   son adresse Ethernet (couche MAC). Afin d'autoriser la communication entre
   deux hotes separes par le pont, il est necessaire que le pont transmette
   les paquets ARP. Un tel protocole n'est pas inclus dans la couche IP,
   puisque qu'il n'apparait qu'avec l'utilisation de l'IP sur Ethernet. Le
   coupe-feu de FreeBSD filtre exclusivement la couche IP et donc tous les
   paquets non-IP (ARP compris) seront transmis sans etre filtres, meme si le
   coupe-feu est configure pour ne rien laisser passer.

   Il est maintenant temps de redemarrer le systeme et de l'utiliser comme
   auparavant: il y aura de nouveaux messages concernant le pont et le
   coupe-feu, mais le pont ne sera pas active et le coupe-feu, etant en mode
   "ouvert", n'interdira aucune operation.

   Si il y a un quelconque probleme, vous devriez le corriger maintenant
   avant de continuer.

4. Activer le pont

   A ce point, pour activer le pont, vous devez executer les commandes
   suivantes (en pensant bien de remplacer les noms des deux interfaces
   reseau fxp0 et xl0 avec les votres):

 # sysctl net.link.ether.bridge.config=fxp0:0,xl0:0
 # sysctl net.link.ether.bridge.ipfw=1
 # sysctl net.link.ether.bridge.enable=1

   La premiere ligne specifie quelles interfaces devront etre activees par le
   pont, la seconde activera le coupe-feu sur le pont et enfin la troisieme
   activera le pont.

  Note:

   Si vous utiliser FreeBSD 5.1-RELEASE ou une version precedente, les
   variables sysctl different. Consultez la page de manuel bridge(4) pour
   plus de details.

   A ce moment l`a, vous devriez etre en mesure d'inserer la machine entre
   deux ensembles d'hotes sans compromettre de capacites de communication
   entre eux. Ensuite, l'etape suivante est d'ajouter les parties
   net.link.ether.bridge.[bla]=[bla] de ces lignes dans le fichier
   /etc/sysctl.conf afin de les executer au demarrage.

5. Configurer le coupe-feu

   Il est maintenant temps de creer votre propre fichier de regle
   personnalise pour le coupe-feu, afin de securiser le reseau interne. Il y
   aura quelques complications `a faire cela parce que toutes les
   fonctionnalites du coupe-feu ne sont pas disponibles sur un pont. En
   outre, il y a une difference entre les paquets qui sont en cours de
   transmission et les paquets qui sont rec,us par la machine locale. En
   general, les paquets entrants traversent le coupe-feu une seule fois, et
   pas deux comme c'est normalement le cas; en fait ils sont filtres `a la
   reception, aussi les regles qui utilisent "out" ou "xmit" n'agiront
   jamais. Personnellement, j'utilise "in via" qui est une ancienne syntaxe,
   mais qui a un sens quand vous la lisez. Une autre limitation est que vous
   etes reduit `a l'utilisation seulement des commandes "pass" ou "drop" pour
   les paquets filtres par un pont. Les choses sophistiquees comme "divert",
   "forward" ou "reject" ne sont pas disponibles. De telles options peuvent
   toujours etre utilisees, mais uniquement sur le trafic `a destination ou
   depuis le pont lui-meme (s'il possede une adresse IP).

   Une nouveaute de FreeBSD 4.0, est le concept de filtrage avec gestion des
   etats (stateful). C'est une grande amelioration pour le trafic UDP, qui
   typiquement est une requete de sortie, suivie peu de temps apres par une
   reponse avec le meme ensemble d'adresses IP et de numero de ports (mais
   avec une source et une destination reservee, bien sur). Pour les
   coupe-feux qui n'ont pas de gestion des etats, il n'y a presque pas de
   possibilite de gerer ce type de trafic en une seule session. Mais avec un
   coupe-feu qui peut se "souvenir" d'un paquet UDP sortant et qui, pour
   quelques minutes, autorise une reponse, la gestion des services UDP est
   triviale. L'exemple suivant montre comment le faire. Il est possible de
   faire la meme chose avec les paquets TCP. Cela vous permet d'eviter
   certaines attaques par refus de service et autres desagreables problemes,
   mais augmente egalement rapidement la taille de votre table des etats.

   Regardons un exemple de configuration. Notez tout d'abord qu'au debut du
   fichier /etc/rc.firewall il y a dej`a des regles standards pour
   l'interface de boucle locale lo0, aussi nous ne devrions pas y faire
   attention. Les regles personnalisees devraient etre placees dans un
   fichier separe (disons /etc/rc.firewall.local) et chargees au demarrage du
   systeme, en modifiant la ligne de /etc/rc.conf ou nous avions defini le
   coupe-feu "ouvert":

 firewall_type="/etc/rc.firewall.local"

  Important:

   Vous devez preciser le chemin complet, sinon il ne sera pas charge avec le
   risque de rester isole du reseau.

   Pour notre exemple imaginez que nous avons l'interface fxp0 connectee vers
   l'exterieur (Internet) et l'interface xl0 vers l'interieur (LAN). Le pont
   possede une adresse IP 1.2.3.4 (il n'est pas possible que votre
   fournisseur d'acces puisse vous donner une adresse de classe A comme
   celle-ci, mais pour cet exemple cela ira).

 # Les choses dont nous avons garde l'etat avant de
 continuer
 add check-state

 # Rejeter les reseaux RFC 1918
 add drop all from 10.0.0.0/8 to any in via fxp0
 add drop all from 172.16.0.0/12 to any in via fxp0
 add drop all from 192.168.0.0/16 to any in via fxp0

 # Autorise la machine pont `a communiquer si elle le desire
 # (si la machine est sans adresse IP, ne pas inclure ces lignes)
 add pass tcp from 1.2.3.4 to any setup keep-state
 add pass udp from 1.2.3.4 to any keep-state
 add pass ip from 1.2.3.4 to any

 # Autorise les hotes internes `a communiquer
 add pass tcp from any to any in via xl0 setup keep-state
 add pass udp from any to any in via xl0 keep-state
 add pass ip from any to any in via xl0

 # Section TCP
 # Autoriser SSH
 add pass tcp from any to any 22 in via fxp0 setup keep-state
 # Autoriser SMTP seulement vers le serveur de courrier
 add pass tcp from any to relay 25 in via fxp0 setup keep-state
 # Autoriser le transfert de zone seulement par le serveur de noms esclave [dns2.nic.it]
 add pass tcp from 193.205.245.8 to ns 53 in via fxp0 setup keep-state
 # Laisser passer les sondes d'ident.  C'est preferable plutot que d'attendre
 # qu'elles s'arretent
 add pass tcp from any to any 113 in via fxp0 setup keep-state
 # Laisser passer la zone de "quarantaine"
 add pass tcp from any to any 49152-65535 in via fxp0 setup keep-state

 # Section UDP
 # Autorise le DNS seulement vers le serveur de noms
 add pass udp from any to ns 53 in via fxp0 keep-state
 # Laisser passer la zone de "quarantaine"
 add pass udp from any to any 49152-65535 in via fxp0 keep-state

 # Section ICMP
 # Laisser passer 'ping'
 add pass icmp from any to any icmptypes 8 keep-state
 # Laisser passer les messages d'erreurs generes par 'traceroute'
 add pass icmp from any to any icmptypes 3
 add pass icmp from any to any icmptypes 11

 # Tout le reste est suspect
 add drop log all from any to any

   Ceux qui parmi vous ont dej`a installe des coupe-feux auparavant pourront
   noter l'absence de certaines choses. En particulier, il n'y a pas de
   regles contre le forgeage d'adresses, en fait nous n'avons pas ajoute:

 add deny all from 1.2.3.4/8 to any in via fxp0

   Cela, bloque les paquets provenant de l'exterieur et clamant etre en
   provenance de votre reseau. C'est quelque chose que vous devriez
   habituellement faire pour etre sur que personne n'essaie de passer outre
   votre filtre de paquet, en generant d'infames paquets qui sont comme s'il
   venaient de l'interieur. Le probleme avec cela est qu'il y a au moins un
   hote de l'exterieur que vous ne voulez pas ignorer: le routeur. Mais
   habituellement, les fournisseurs d'acces contrent le forgeage sur leur
   routeur, aussi nous ne devons pas nous en preoccuper plus que cela.

   La derniere regle semble etre une copie conforme de la regle par defaut,
   qui ne laisse passer rien de ce qui n'est pas specifiquement autorise.
   Mais il y a une difference: tout le trafic suspect sera trace.

   Il y a deux regles pour faire passer le trafic SMTP et DNS vers le serveur
   de courrier et le serveur de noms, si vous en avez. Evidemment l'ensemble
   du jeu de regle devra etre arrange selon vos gouts personnels, c'est juste
   un exemple particulier (le format des regles est decrit precisement dans
   la page de manuel ipfw(8)). Notez qu'afin que "relay" et "ns" puissent
   fonctionner, les services de resolution de nom doivent fonctionner avant
   que le pont soit active. C'est un exemple pour etre sur que vous avez
   configure l'adresse IP sur la bonne carte reseau. Alternativement il est
   possible de specifier l'adresse IP au lieu du nom (necessaire si la
   machine est sans adresse IP).

   Les personnes qui ont l'habitude de configurer des coupe-feux ont
   probablement egalement utilise soit une regle "reset" soit une regle
   "forward" pour les paquets ident (TCP port 113). Malheureusement, ce n'est
   pas une option applicable avec un pont, aussi la meilleure solution est de
   les laisser passer vers leur destination. Aussi longtemps que la machine
   de destination ne fait pas tourner un daemon ident, cela est relativement
   inoffensif. L'alternative est de bloquer les connexions sur le port 113,
   ce qui pose probleme avec des services comme l'IRC (la sonde d'ident doit
   s'arreter).

   La seule autre chose qui est un peu etrange que vous avez peut-etre note
   est qu'il y a une regle pour laisser le pont communiquer, et une autre
   pour les hotes internes. Rappelez-vous que c'est parce que les deux
   ensembles de trafic prendront un chemin different `a travers le noyau et
   dans le filtre de paquet. Le reseau interne ira `a travers le pont, alors
   que la machine locale utilisera la pile IP normale pour communiquer. Ainsi
   les deux regles s'occupent de cas differents. La regle "in via fxp0"
   fonctionne pour les deux chemins. En general, si vous employez des regles
   "in via" dans tout le filtre, vous devrez faire une exception pour les
   paquets generes localement, parce qu'ils ne sont pas passes par une de nos
   interfaces.

6. Participants

   Plusieurs parties de cet article proviennent, et furent mises `a jour et
   adaptees d'un vieux texte sur les ponts, ecrit par Nick Sayer. Cet article
   est egalement inspire d'une introduction sur les ponts de Steve Peterson.

   Un grand merci `a Luigi Rizzo pour l'implementation du code de pont dans
   FreeBSD et pour le temps qu'il a passe `a repondre `a toutes mes questions
   `a ce sujet.

   Un remerciement egalement `a Tom Rhodes qui a supervise mon travail de
   traduction de l'Italien (langue d'origine de cet article) `a l'Anglais.
