pfSense, le firewall convivial

GNU/Linux Magazine HS n° 074 | septembre 2014 | Benjamin Sans
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
Dans la vie, on a tous besoin d'un firewall. Il existe dans le monde du libre grosso modo deux familles : Packet Filter (PF) côté BSD (existe en différents parfums) et Netfilter côté Linux, avec le célèbre iptables comme interface de pilotage. Dans cet article, nous parlerons d'un frontend à PF nommé pfSense.

Avec pfSense, ma grand-mère peut configurer son firewall en clic-clic-convi sans avoir à se palucher la documentation toute poilue sur PF, qui avouons-le, pourrait en faire reculer plus d'un.

Afin d'illustrer cet article et démontrer la puissance et la convivialité de l'outil, nous commencerons par présenter les fonctionnalités de base, puis nous mettrons en place un cluster de pfSense (actif/passif) et enfin, nous verrons une configuration avancée à base de multi-wan en failover et/ou load-balancing.

1. En savoir plus sur pfSense

pfSense est ce qu'on appelle une appliance. C'est-à-dire qu'il s'agit d'une solution toute packagée et prête à l'emploi.

La solution est donc composée d'un système minimaliste basé sur FreeBSD embarquant les outils nécessaires à la réalisation d'une passerelle réseau (DNS, DHCP, VPN, etc.), un serveur web et une interface de configuration en PHP. pfSense est né en 2004 en tant que fork du projet m0n0wall [1], une appliance également basée sur FreeBSD, mais orientée matériel embarqué, là où pfSense vise une plus large gamme de machines (en passant par des machines virtuelles).

Il existe différentes images fournies par le projet permettant de récupérer, soit une ISO afin d'installer notre firewall sur à peu près n'importe quelle machine physique, soit une virtual appliance, afin de créer une machine virtuelle prête à l'emploi, soit une image « raw », généralement utilisée pour installer pfSense sur des boîtiers dédiés au firewalling qui ne disposent en général que d'un disque dur classique et/ou d'un lecteur de cartes Compact-Flash/SD. C'est par exemple le cas des boîtiers vendus par OSNet [2], l'un des contributeurs du projet pfSense.

2. Mise en place de pfSense

2.1 Avant de courir, on apprend à marcher

Comme expliqué plus haut, nous allons mettre en place une solution de firewalling en différentes étapes avec une complexité croissante. Nous ne traiterons ici que des fonctionnalités de filtrage et de routage avancé, mais les possibilités de pfSense ne se limitent pas uniquement à ça. Au cours de l'article, il nous arrivera de croiser quelques fonctionnalités annexes, mais ces dernières ne bénéficieront pas d'explications détaillées.

La figure 1 représente notre réseau cible. Voici la configuration dont nous disposons :

- Une DMZ sur le réseau 192.168.43.0/24,

- Un LAN sur le réseau 192.168.41.0/24,

- Un FAI n°1 sur le réseau 10.42.42.0/24,

- Un FAI n°2 sur le réseau 10.43.43.0/24,

- Deux machines pfSense ayant respectivement sur le LAN les adresses 192.168.41.252 et 192.168.41.253, et sur la DMZ 192.168.43.252 et 192.168.43.253,

- Deux IP flottantes pour le LAN et la DMZ : 192.168.41.254 et 192.168.43.254.

Fig. 1 : Schéma du réseau cible

Vous l'aurez compris, nos IP flottantes serviront à notre cluster. Notre maquette prendra place au sein d'un environnement virtuel et j'ai choisi comme support d'installation de mes firewalls une image ISO. Le but de l'opération est de dédier un accès Internet à notre DMZ, et un deuxième à notre LAN. Le tout avec des fonctionnalités de failover en cas d'indisponibilité de l'un ou l'autre des accès. On envisagera également le cas d'une machine en DMZ consommant beaucoup de bande passante (un proxy par exemple) et pour ce cas particulier, nous mettrons en place, en plus du failover, une règle de load-balancing sur nos liens.

2.2 Ensuite, on s'échauffe

L'installation via l'image ISO est relativement simple, l'installeur nous pose quelques questions. À la fin du processus, la machine redémarre puis propose un menu textuel comme on peut le voir sur la figure 2.

Fig. 2 : Menu textuel de pfSense

Si vous avez choisi d'installer pfSense sur une machine physique, il ne vous reste plus qu'à brancher un câble sur l'interface LAN afin de passer à la suite de la configuration via l'interface web à l'adresse http://192.168.1.1/. Dans mon cas, étant sur un environnement virtuel, je vais configurer tout de suite mon interface LAN sur le bon subnet. Pour ce faire, je choisis l'option 2). À la fin de la configuration, l'interface web est démarrée et écoute sur l'adresse que l'on vient de lui assigner. Arrivés sur l'interface web, un login et un mot de passe nous sont demandés. Par défaut, le login est admin, et le mot de passe est pfsense. Aussitôt, un wizard d'installation démarre. On répond aux quelques questions posées.

La première étape nous demande les informations suivantes :

- Nom de la machine : fw1

- Domaine : demo.gcu.ftw

- DNS primaire : 8.8.8.8

- DNS secondaire : 8.8.4.4

- Surcharge DNS : non

Nous devons renseigner des DNS joignables par nos deux accès Internet. Pour l'exemple, j'ai choisis les DNS de chez Google, mais vous pouvez parfaitement les remplacer par d'autres s'ils répondent à vos critères.

La deuxième étape nous permet de configurer le serveur de temps. Nous laissons la configuration par défaut.

Pour la troisième étape, nous pouvons configurer notre interface WAN (pour l'instant, lors de l'installation, nous n'avions assigné qu'une seule interface WAN, c'est cette dernière que nous configurons ici). On choisit comme type de configuration static, et nous renseignons les paramètres suivants :

- IP Address : 10.42.42.1/24

- Upstream Gateway : 10.42.42.254

Puis, nous passons à l'étape suivante qui nous permet de configurer l'adresse de notre interface LAN. Cette étape ayant déjà été réalisée dans mon cas, je passe à l'étape suivante.

Désormais, on choisit un nouveau mot de passe pour accéder à notre firewall.

Voilà, notre firewall est presque prêt, il ne reste plus qu'à recharger sa configuration en cliquant sur le bouton Reload. À la fin du processus, on peut cliquer sur le deuxième lien afin d'accéder à notre interface de configuration. Notre firewall est enfin prêt comme vous pouvez le constater sur la figure 3.

Fig. 3 : Écran d'accueil de pfSense

3. Démarrage

3.1 On démarre en douceur

Il reste en théorie deux (ou plus suivant votre machine) ports non configurés pour le moment. On se rend donc dans le menu Interface > (assign). Mes interfaces sont réparties de la sorte :

- em0 -> FAI1

- em1 -> FAI2

- em2 -> LAN

- em3 -> DMZ

Pour le moment, les deux seules interfaces configurées sont em0 et em2. De plus, le nom assigné à mon interface em0 ne me convient pas : je vais le modifier en cliquant sur son nom actuel (WAN dans mon cas). On modifie le champ Description, puis on clique sur le bouton Save en bas de la page.

Note

Un message d'avertissement apparaît pour nous indiquer des modifications de configuration non appliquées. Nous pouvons ignorer ce message pour l'instant, car nous appliquerons les modifications une fois notre configuration terminée.

On retourne sur la page Interface > (assign) pour passer à la configuration de l'interface em1. On clique sur le nom qui lui a été attribué par défaut ( OPT1 dans mon cas). Puis, on renseigne les champs suivants de la sorte :

- Description : FAI2

- IPv4 Configuration Type : Static IPv4

- IPv4 address : 10.43.43.1/24

- IPv4 Upstream Gateway : on clique sur le lien add a new one, un nouveau formulaire apparaît :

   - Gateway Name : FAI2GW

   - Gateway IPv4 : 10.43.43.254

   - Description : FAI n°2

   - On clique sur Save Gateway

Puis, on clique sur le bouton Save.

Et enfin, on passe à la configuration de l'interface em3. Ça se passe comme précédemment. Voici la valeur de nos champs :

- Description : DMZ

- IPv4 Conviguration Type : Static IPv4

- IPv4 address : 192.168.43.252/24

Puis, Save.

Lors de la configuration de notre interface FAI2, nous avons créé une Gateway. Pour notre interface FAI1, configurée via le wizard, la gateway attachée se nomme WANGW. Nous allons modifier cela afin d'uniformiser avec la nomenclature utilisée pour l'interface FAI2. Nous nous rendons donc sur la page System > Routing. pfSense ne nous permet pas de renommer une gateway, nous allons donc en re-créer une tout en supprimant celle que l'on souhaitait renommer. Il suffit de cliquer sur le symbole x situé juste à côté de notre gateway source. Puis, on en crée une nouvelle en cliquant sur le bouton +. Les informations renseignées sont :

- Interface : FAI1

- Name : FAI1GW

- Gateway : 10.42.42.254

- Description : FAI n°1

On coche également la case Default Gateway, puis on clique sur Save.

Suite à ces modifications, il est nécessaire de retourner dans la configuration de l'interface FAI1 afin de lui assigner la gateway nouvellement créée.

Voilà, notre setup commence à ressembler à quelque chose. Pour un peu plus de confort, nous allons activer le DHCP sur nos interfaces DMZ et LAN si nécessaire. Dans mon cas, le DHCP sur l'interface LAN a été configuré à l'installation de pfSense. Pour l'interface DMZ, ça se passe en cliquant sur Services > DHCP Server : on sélectionne notre interface, on coche ensuite la case Enable DHCP server on DMZ interface, puis on définit la plage d'adresses à servir sur la ligne Range.

3.2 En pratique, qu'est-ce que ça donne ?

3.2.1 Ça marche, tout simplement !

La partie « câblage » est maintenant terminée. Nous configurons tout de suite un poste client qui sera relié à notre LAN. Ce dernier obtient tout naturellement une adresse IP, une route et un DNS.

# ip addr sh eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
 link/ether 52:54:00:7b:2a:76 brd ff:ff:ff:ff:ff:ff
 inet 192.168.41.10/24 brd 192.168.41.255 scope global eth0
 inet6 fe80::5054:ff:fe7b:2a76/64 scope link
 valid_lft forever preferred_lft forever
# ip route sh
default via 192.168.41.252 dev eth0
192.168.41.0/24 dev eth0 proto kernel scope link src 192.168.41.10
# cat /etc/resolv.conf
domain demo.gcu.ftw
search demo.gcu.ftw
nameserver 192.168.41.252

3.2.2 Et les lutins, par où passent-ils ?

Quelques lignes plus haut, nous avons indiqué que notre interface FAI1 servirait de route par défaut pour notre firewall. C'est effectivement ce que l'on peut observer en essayant de sortir (note : ici, je ne fais que sortir de ma machine hôte en atteignant la passerelle de cette dernière).

# traceroute 172.16.0.1
traceroute to 172.16.0.1 (172.16.0.1), 30 hops max, 60 byte packets
 1 fw1.demo.gcu.ftw (192.168.41.252) 0.325 ms 0.735 ms 0.814 ms
 2 10.42.42.254 (10.42.42.254) 1.513 ms 1.574 ms 1.566 ms
 3 172.16.0.1 (172.16.0.1) 4.453 ms 4.489 ms 4.599 ms

4. À deux, c'est mieux !

4.1 Main dans la main, on va plus loin

Maintenant que la course est lancée et que nous avons du réseau, nous allons sécuriser notre infrastructure en mettant en place un petit cluster de pfSense. On configure donc un nouveau firewall, soit en clonant le premier (en cas d'environnement virtuel comme dans mon exemple), soit en en réinstallant un deuxième. Ce firewall se nommera fw2.demo.gcu.ftw. Cette fois, les adresses des différentes interfaces seront :

- FAI1 : 10.42.42.2/24

- LAN : 192.168.41.253/24

- FAI2 : 10.43.43.2/24

- DMZ : 192.168.43.253/24

Une fois que nos deux firewalls sont opérationnels, nous configurons la haute disponibilité ou HA. On se rend sur la page System > High Avail. Sync. Les explications sur la page sont relativement claires. La configuration est à faire sur les deux firewalls. Sur le premier, qui sera notre master, nous allons avoir la configuration suivante :

- Synchronize States : coché

- Synchronize Interface : LAN (comme vous pouvez le voir, ceci n'est pas recommandé. L'idéal serait d'avoir une interface dédiée à ça)

- pfsync Synchronize Peer IP : 192.168.41.253

- Synchronize Config to IP : 192.168.41.253

- Remote System Username : admin

- Remote System Password : le mot de passe du compte admin sur le deuxième firewall.

Puis, nous cochons toutes les cases suivantes. Ces options permettent de choisir les éléments de notre configuration à synchroniser.

Sur le deuxième firewall, la configuration est la suivante :

- Synchronize States : coché

- Synchronize Interface : LAN

- pfsync Synchronize Peer IP : 192.168.41.252

Nous ne renseignons pas les valeurs de Synchronize Config to IP, Remote System Username et Remote System Password, comme indiqué en gras, car nous sommes sur le nœud secondaire. Enfin, nous cochons toutes les cases suivantes comme sur le premier firewall.

4.2 Quelques préliminaires

Désormais, nous pouvons vérifier que nos firewalls sont correctement synchronisés. Nous allons par exemple créer une règle de filtrage sur l'interface FAI1 pour empêcher les connexions extérieures sur le port 8080. La configuration se fera sur le firewall fw1. On clique sur le lien Firewall > Rules, on sélectionne notre interface FAI1, puis nous ajoutons une nouvelle règle en cliquant sur le bouton +. Cette règle contiendra :

- Action : Block

- Interface : FAI1

- TCP/IP Version : IPv4

- Protocol : TCP

- Source : Type : any

- Destination : Type : any

- Destination port range : From : 8080, To : 8080

- Description : Regle test 8080

Puis, Save et Apply changes. En se rendant sur la page Firewall > Rules du second firewall fw2, on observera que la règle a bien été répliquée.

4.3 Fuuuuuuuuuuusion

Alors, maintenant que l'on a un couple de firewalls capables de travailler en binôme, il ne reste plus qu'à rendre ce cluster transparent pour nos clients. Pour ce faire, nous allons utiliser des IP virtuelles qui pourront basculer d'une machine à l'autre en cas de problème sur un des nœuds. On se rend sur la page Firewall > Virtual IPs du firewall fw1, puis on clique sur le bouton +. Les paramètres seront :

- Type : CARP

- Interface : LAN

- IP Address(es) : 192.168.41.254/24

- Virtual IP Password : un mot de passe qui sera identique sur nos deux firewalls.

- VHID Group : 1 (cette valeur devra être identique sur nos deux firewalls également)

- Advertising Frequency : Base : 1, Skew : 0

- Description : IP virtuelle LAN

Puis, Save et Apply changes.

Note

CARP signifie Common Address Redundancy Protocol, c'est une implémentation libre du protocole VRRP (Virtual Router Redundancy Protocol) permettant à plusieurs machines sur un même réseau de partager une même adresse IP.

La configuration a normalement été automatiquement appliquée sur notre deuxième firewall et la valeur de Advertising Frequency adaptée. Cette valeur indique la priorité afin de déterminer quel nœud est maître. La valeur la plus basse est prioritaire.

On répète l'opération pour l'interface DMZ en utilisant cette fois comme adresse 192.168.43.254/24 et comme VHID Group la valeur 2.

Dernier petit détail à régler pour rendre tout cela vraiment transparent pour nos clients, nous allons indiquer au serveur DHCP qu'il doit présenter nos IP virtuelles comme adresses de routeurs et de DNS. On se rend sur la page Services > DHCP Server, on sélectionne notre interface, puis on renseigne les champs DNS Server et Gateway avec respectivement les adresses 192.168.41.254 et 192.168.43.254 pour le LAN et la DMZ. Comme toujours, la configuration a été automatiquement répliquée sur la machine fw2.

On démarre un client sur le LAN pour voir ce qu'il se passe :

# ip route sh
default via 192.168.41.254 dev eth0
192.168.41.0/24 dev eth0 proto kernel scope link src 192.168.41.10
# cat /etc/resolv.conf
domain demo.gcu.ftw
search demo.gcu.ftw
nameserver 192.168.41.254
# traceroute 172.16.0.1
traceroute to 172.16.0.1 (172.16.0.1), 30 hops max, 60 byte packets
 1 fw1.demo.gcu.ftw (192.168.41.252) 0.597 ms 0.589 ms 0.573 ms
 2 10.42.42.254 (10.42.42.254) 1.592 ms 1.603 ms 1.637 ms
 3 172.16.0.1 (172.16.0.1) 1.899 ms 2.522 ms 3.312 ms
# ping gcu.info
PING gcu.info (194.213.125.0) 56(84) bytes of data.
64 bytes from zoneX.GCU-Squad.org (194.213.125.0): icmp_req=1 ttl=47 time=39.8 ms
64 bytes from zoneX.GCU-Squad.org (194.213.125.0): icmp_req=2 ttl=47 time=37.8 ms
^C
--- gcu.info ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 37.811/38.846/39.882/1.054 ms

A priori, tout va bien, on a récupéré la bonne adresse de routeur et de DNS et notre machine a bien accès au réseau.

Petit test pour contrôler que notre cluster est opérationnel : nous débranchons le nœud primaire (voir figure 4).

# traceroute 172.16.0.1
traceroute to 172.16.0.1 (172.16.0.1), 30 hops max, 60 byte packets
 1 fw2.demo.gcu.ftw (192.168.41.253) 0.583 ms 0.622 ms 0.702 ms
 2 10.42.42.254 (10.42.42.254) 1.726 ms 1.808 ms 1.848 ms
 3 172.16.0.1 (172.16.0.1) 2.049 ms 2.507 ms 2.990 ms
# ping gcu.info
PING gcu.info (194.213.125.0) 56(84) bytes of data.
64 bytes from zoneX.GCU-Squad.org (194.213.125.0): icmp_req=1 ttl=47 time=40.7 ms
64 bytes from zoneX.GCU-Squad.org (194.213.125.0): icmp_req=2 ttl=47 time=41.1 ms
^C
--- gcu.info ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 40.791/40.964/41.138/0.266 ms

La bascule est effectivement transparente pour notre client !

Fig. 4 : Effet du débranchement du nœud primaire du cluster

5. Relais 2 x 100M

5.1 Passage de témoin

Maintenant que la partie firewall de notre infrastructure est redondée, il nous reste à sécuriser l'accès à Internet en tirant profit des deux liens dont nous disposons. Nous nous contenterons, pour commencer, d'un failover sur les liens (mode actif/passif). Bien entendu, on aura pris le soin de redémarrer notre firewall fw1. La configuration sera encore une fois réalisée sur celui-ci. On se rend sur la page System > Routing, puis sur l'onglet Groups, et on clique sur +.

Les valeurs à indiquer sont :

- Group Name : FAI1FO

- Gateway Priority :

Gateway Tier Virtual IP Description
FAI2GW Tier 2 Interface Address FAI n°2
FAI1GW Tier 1 Interface Address FAI n°1

Puis, Save et Apply changes.

On réitère l'opération pour FAI2 :

- Group Name : FAI2FO

- Gateway Priority :

Gateway Tier Virtual IP Description
FAI2GW Tier 1 Interface Address FAI n°2
FAI1GW Tier 2 Interface Address FAI n°1

Puis, Save et Apply changes.

Maintenant, il faut créer une règle de routage utilisant ce groupe de gateways. Cette fonctionnalité est très puissante, car elle dispose d'une granularité à la règle près ! (C'est-à-dire que l'on peut choisir de faire transiter une partie du trafic par une route et le reste par l'autre, en utilisant comme critère une IP source, un port de destination, etc.). La configuration s'effectue dans Firewall > Rules, puis on sélectionne l'interface sur laquelle on veut créer nos règles. Ici, ce sera l'interface LAN pour commencer. Sur cette interface, des règles par défaut ont été créées par le wizard au moment de l'installation (voir figure 5). Nous allons éditer la règle dont la description est Default allow LAN to any rule en cliquant sur le bouton e situé à droite de cette dernière. Nous descendons jusqu'à la rubrique Advanced features, puis sur la ligne Gateway, on clique sur Advanced et dans le drop-down qui apparaît, on sélectionne FAI1FO, puis Save et Apply changes.

Fig. 5 : Configuration des règles de routage

Depuis notre client, on refait un test :

# traceroute 172.16.0.1
traceroute to 172.16.0.1 (172.16.0.1), 30 hops max, 60 byte packets
 1 10.42.42.254 (10.42.42.254) 3.830 ms 5.123 ms 5.163 ms
 2 172.16.0.1 (172.16.0.1) 5.254 ms 5.288 ms 5.356 ms

Puis, nous simulons une panne sur le lien FAI1. Pour ce faire, étant donné que je me trouve dans un environnement virtuel, je me contente d'ajouter une règle iptables (ma machine hôte étant un Linux) bloquant tous les flux par défaut sur mon interface :

# iptables -A INPUT -i wan1 -j DROP
# iptables -A OUTPUT -o wan1 -j DROP

Réaction immédiate dans les logs de pfSense, Status > System Logs, onglet Gateways, on remarque la ligne suivante en bas du tableau :

apinger: ALARM: FAI1GW(10.42.42.254) *** down ***

On teste le résultat sur notre client :

# traceroute 172.16.0.1
traceroute to 172.16.0.1 (172.16.0.1), 30 hops max, 60 byte packets
 1 10.43.43.254 (10.43.43.254) 1.461 ms 1.502 ms 1.522 ms
 2 172.16.0.1 (172.16.0.1) 2.058 ms 2.424 ms 2.915 ms
# ping gcu.info
PING gcu.info (194.213.125.0) 56(84) bytes of data.
64 bytes from zoneX.GCU-Squad.org (194.213.125.0): icmp_req=1 ttl=47 time=40.8 ms
64 bytes from zoneX.GCU-Squad.org (194.213.125.0): icmp_req=2 ttl=47 time=41.1 ms
^C
--- gcu.info ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 40.841/40.971/41.102/0.240 ms

La bascule a bien eu lieu, nous passons désormais par l'interface FAI2 (adresse 10.43.43.254) pour sortir, et notre client a toujours accès à Internet. Et ce, bien entendu, sans aucune intervention de notre part sur le client ! On réactive notre interface FAI1 :

# iptables -L -n -v --line-number
Chain INPUT (policy ACCEPT 2639 packets, 621K bytes)
num pkts bytes target prot opt in out source destination
1 1065 85200 DROP all -- wan1 * 0.0.0.0/0 0.0.0.0/0

Chain FORWARD (policy ACCEPT 2827 packets, 577K bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 2943 packets, 289K bytes)
num pkts bytes target prot opt in out source destination
1 2 482 DROP all -- * wan1 0.0.0.0/0 0.0.0.0/0
# iptables -D INPUT 1
# iptables -D OUTPUT 1

Dans les logs, l'alerte est annulée :

apinger: alarm canceled: FAI1GW(10.42.42.254) *** down ***

Et un traceroute sur notre client indique bien que ce dernier passe à nouveau par l'adresse 10.42.42.254 pour sortir.

Il resterait à procéder aux mêmes manipulations pour l'interface DMZ. Je laisse le soin aux lecteurs de réaliser cet exercice.

5.2 Place au sprint !

On dispose désormais d'une redondance à tous les niveaux, mais l'idéal serait de pouvoir mutualiser nos accès pour les éléments consommateurs de bande passante. On va prendre l'exemple du proxy, qui en entreprise peut consommer pas mal de ressources réseau en fonction du moment de la journée, voire en fonction d'événements sportifs (comme par exemple une coupe du monde de foot, ou le tour de France au moment de la rédaction de cet article).

La mise en place d'un tel système est similaire à ce qu'on vient de faire pour le failover, à quelques différences près. On commence, comme tout à l'heure, par se rendre sur la page System > Routing, onglet Groups, puis on clique sur le bouton +. Cette fois, les paramètres sont les suivants :

- Group Name : FAI12LB

- Gateway Priority :

Gateway Tier Virtual IP Description
FAI2GW Tier 1 Interface Address FAI n°2
FAI1GW Tier 1 Interface Address FAI n°1

Puis, Save et Apply changes. Ici, la magie opère lorsque nos liens sont configurés avec le même Tier ; en effet, aucun n'est prioritaire sur l'autre, c'est ce qui permet le load-balancing.

Et enfin, nous ajoutons notre règle de routage avancé en nous rendant sur la page Firewall > Rules, onglet DMZ. En principe, il n'existe ici aucune règle (sauf si vous avez réalisé l'exercice indiqué juste au-dessus), comme on peut le voir sur la figure 6.

Fig. 6 : Absence de règles pour la DMZ

On clique sur le bouton + afin de créer notre règle. Les paramètres à renseigner sont les suivants :

- Action : Pass

- Interface : DMZ

- TCP/IP Version : IPv4

- Protocol : TCP

- Source : Type : DMZ net

- Destination : Type : any

- Destination port range : from : 80, to : 80

- Description : Load-balancing HTTP

- Gateway : Advanced > FAI12LB

Puis, Save et Apply changes. Cette seule règle ne suffit pas pour nos tests, il faut en effet autoriser les machines de notre DMZ à parler au DNS par exemple. Pour simplifier, nous allons créer une nouvelle règle autorisant nos machines en DMZ à faire ce qu'elles veulent, à part communiquer avec notre LAN (on conviendra que dans la vraie vie on adaptera les règles plus finement). On clique à nouveau sur le bouton + et on indique cette fois ces paramètres :

- Action : Pass

- Interface : DMZ

- TCP/IP Version : IPv4

- Protocol : any

- Source : Type : DMZ net

- Destination : on coche la case not, puis Type : LAN net

- Description : Autorise tout sauf LAN

- Gateway : Advanced > FAI2FO

Puis, Save et Apply changes. À noter également que cette règle doit se situer après la règle Load-balancing HTTP, car sur PF, la première règle qui correspond est appliquée.

5.3 Les concurrents sont à quelques octets de la ligne d'arrivée

Testons tout cela ! Au moment des tests, je dispose d'une bande passante d'à peu près 480 KB/s, comme on peut l'observer avec le test suivant :

# wget -O /dev/null http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
--2014-07-27 19:08:41-- http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
Resolving ftp.fr.netbsd.org (ftp.fr.netbsd.org)... 132.227.74.11, 2001:660:3302:282a:204:75ff:fe9f:9e11
Connecting to ftp.fr.netbsd.org (ftp.fr.netbsd.org)|132.227.74.11|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 346933248 (331M) [application/octet-stream]
Saving to: `/dev/null'

1% [> ] 3,976,208 484K/s eta 11m 36s ^C

Afin de valider que mes ports sont bien load-balancés, je vais ajouter de la QoS sur mon hôte. Je limite chacune des interfaces correspondant à mes liens FAI1 et FAI2 à une bande passante de 128 KB/s, soit environ 250 KB/s cumulé.

# iptables -A INPUT -i wan2 -t mangle -p tcp --dport 80 -j MARK --set-mark 10
# iptables -A INPUT -i wan1 -t mangle -p tcp --dport 80 -j MARK --set-mark 10
# tc qdisc add dev wan1 root handle 1:0 htb default 10
# tc class add dev wan1 parent 1:0 classid 1:10 htb rate 128kbps ceil 150kbps prio 0
# tc filter add dev wan1 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:10
# tc qdisc add dev wan2 root handle 1:0 htb default 10
# tc class add dev wan2 parent 1:0 classid 1:10 htb rate 128kbps ceil 150kbps prio 0
# tc filter add dev wan2 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:10

Cette fois, je dois lancer deux téléchargements parallèles afin d'utiliser mes deux liens. En effet, nous avons configuré un load-balancing et non une agrégation de liens. Afin de tirer parti du maximum de bande passante, il faut donc un minimum de 2 connexions simultanées. Résultat, je plafonne à une centaine de KB/s sur chacun des téléchargements :

# wget -O /dev/null http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
--2014-07-27 19:19:53-- http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
Resolving ftp.fr.netbsd.org (ftp.fr.netbsd.org)... 132.227.74.11, 2001:660:3302:282a:204:75ff:fe9f:9e11
Connecting to ftp.fr.netbsd.org (ftp.fr.netbsd.org)|132.227.74.11|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 346933248 (331M) [application/octet-stream]
Saving to: `/dev/null'

0% [ ] 2,189,376 87.7K/s eta 69m 55s ^C
# wget -O /dev/null http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
--2014-07-27 19:19:54-- http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
Resolving ftp.fr.netbsd.org (ftp.fr.netbsd.org)... 132.227.74.11, 2001:660:3302:282a:204:75ff:fe9f:9e11
Connecting to ftp.fr.netbsd.org (ftp.fr.netbsd.org)|132.227.74.11|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 346933248 (331M) [application/octet-stream]
Saving to: `/dev/null'

0% [ ] 1,856,336 89.0K/s eta 74m 2s ^C

On va de nouveau couper une interface :

# iptables -A OUTPUT -o wan1 -j DROP
# iptables -A INPUT -i wan1 -j DROP

La bande passante cumulée est effectivement divisée par deux :

# wget -O /dev/null http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
--2014-07-27 19:25:13-- http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
Resolving ftp.fr.netbsd.org (ftp.fr.netbsd.org)... 132.227.74.11, 2001:660:3302:282a:204:75ff:fe9f:9e11
Connecting to ftp.fr.netbsd.org (ftp.fr.netbsd.org)|132.227.74.11|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 346933248 (331M) [application/octet-stream]
Saving to: `/dev/null'

0% [ ] 616,848 67.7K/s eta 2h 21m ^C
# wget -O /dev/null http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
--2014-07-27 19:25:09-- http://ftp.fr.netbsd.org/pub/NetBSD/iso/6.1/NetBSD-6.1-amd64.iso
Resolving ftp.fr.netbsd.org (ftp.fr.netbsd.org)... 132.227.74.11, 2001:660:3302:282a:204:75ff:fe9f:9e11
Connecting to ftp.fr.netbsd.org (ftp.fr.netbsd.org)|132.227.74.11|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 346933248 (331M) [application/octet-stream]
Saving to: `/dev/null'

0% [ ] 876,040 34.8K/s eta 2h 1m ^C

Conclusion

Cet article touche à sa fin. Nous n'avons survolé ici qu'une infime partie des fonctionnalités offertes par pfSense, mais ces quelques fonctions permettent de mettre en place des configurations relativement complexes. Pour les fonctionnalités classiques que l'on est en mesure d'attendre d'une passerelle réseau (comme le filtrage, le NAT, les services DNS, DHCP, etc.), je vous laisse explorer le site du projet pfSense [3] et en particulier son wiki [4], ainsi que son forum [5].

J'espère que cette petite mise en bouche vous donnera l'envie de prendre ou reprendre le contrôle de votre réseau, bien que je me sois focalisé sur des besoins plutôt orientés entreprise.

Pour être tout à fait franc avec vous, je suis en général plutôt mauvais en réseau (je sais à peine calculer un netmask), mais pfSense, en quelques clics, m'a rendu accessibles des fonctionnalités que je pensais inutilisables avec mon faible niveau. C'est cette facilité de prise en main de l'outil que j'ai souhaité vous retranscrire au travers de ces quelques lignes.

Références

[1] Site du projet m0n0wall : http://m0n0.ch/wall/

[2] Site de OSNet, contributeur au projet pfSense : http://www.osnet.eu/

[3] Site du projet pfSense : https://www.pfsense.org/

[4] Wiki du projet pfSense : https://doc.pfsense.org/index.php/Main_Page

[5] Forum du projet pfSense : https://forum.pfsense.org/