Un pare-feu ne « bloque » rien en bloc : il lit des en-têtes, couche par couche, et chaque couche autorise un type de filtrage différent. Tour d’horizon de la couche 2 à la couche 7, avec pfSense comme cas d’école.
L’essentiel en 30 secondes
- Un pare-feu est avant tout un lecteur d’en-têtes. Plus il désencapsule profond, plus le filtrage est fin — et plus il coûte cher en CPU.
- Couche 2 : filtrage MAC/VLAN/EtherType. Marginal en routage, indispensable en bridge transparent.
- Couche 3 : la brique historique. IP source/destination, protocole, ICMP, NAT. C’est du packet filtering.
- Couche 4 : ports TCP/UDP et surtout la table d’états. C’est le stateful inspection, le vrai socle des pare-feux modernes.
- Couches 5-6 : là où TLS complique tout. Le SNI et le certificat sont les derniers éléments lisibles sans déchiffrer.
- Couche 7 : filtrage applicatif, IDS/IPS, filtrage d’URL et de DNS. Nécessite du DPI, et souvent de casser le TLS.
- Le piège : un pare-feu ne traite pas les paquets dans l’ordre 1 → 7. Le pipeline réel est plus tordu, et c’est ce qui explique 80 % des « pourquoi ma règle ne matche pas ».
Pourquoi reparler d’OSI quand on parle pare-feu
Après les articles sur le câblage RJ45 (couche 1), les adresses MAC (couche 2), l’IP et le routage (couche 3), TCP et les ports (couche 4) et enfin l’application (couche 7), la question qui revient chez les lecteurs qui préparent le TSSR est toujours la même : « OK, mais concrètement, mon pare-feu il travaille à quelle couche ? »
La réponse tient en un mot : toutes. Et c’est justement ça qui mérite un article.
Un pare-feu, quel qu’il soit — une VM pfSense montée en dix minutes pour un lab, ou une appliance en production — fait toujours la même chose : il reçoit une trame, il la désencapsule couche par couche, et à chaque couche épluchée il gagne le droit de prendre une décision plus fine. Le modèle OSI n’est pas ici un schéma de cours : c’est littéralement la carte des points de décision de l’appareil.
Là où ça devient intéressant, c’est que chaque couche a un coût. Filtrer sur une IP, c’est une comparaison de 4 octets. Filtrer sur « est-ce que ce flux HTTPS est du Dropbox ou du OneDrive », c’est déchiffrer du TLS, reconstruire un flux, et le passer dans un moteur de signatures. Entre les deux, il y a trois ordres de grandeur de CPU. Tout le métier consiste à mettre le bon filtre à la bonne couche.
Cet article prend pfSense comme cas d’école — parce qu’il est gratuit, qu’on le monte en dix minutes dans une infra perso, et que sa transparence (c’est du pf d’OpenBSD, du Suricata, du Squid — des briques libres qu’on peut inspecter) en fait un excellent support pour comprendre ce qui se passe, là où une appliance propriétaire masque la mécanique.
La carte : une couche, un type de filtrage
| Couche OSI | Ce que le pare-feu lit | Type de filtrage | Chez pfSense |
|---|---|---|---|
| 2 — Liaison | MAC src/dst, tag 802.1Q, EtherType | Filtrage MAC, isolation VLAN, anti-ARP-spoofing | Interfaces VLAN, bridge filtrant, Ethernet Rules (pfSense Plus uniquement) |
| 3 — Réseau | IP src/dst, protocole, TTL, flags de fragmentation | Packet filtering, ACL, NAT, anti-spoofing | Règles pf, aliases, Outbound NAT, pfBlockerNG (GeoIP/listes) |
| 4 — Transport | Ports TCP/UDP, flags TCP, séquence | Stateful inspection, table d’états, contrôle de débit | State table (pfctl -s state), options keep state, synproxy, limiters |
| 5-6 — Session / Présentation | Handshake TLS, SNI, certificat, ALPN | Filtrage par nom de domaine sans déchiffrer, contrôle du chiffrement | Filtrage SNI via HAProxy / Suricata, DNSBL pfBlockerNG |
| 7 — Application | Payload complet, URL, méthode HTTP, requête DNS, fichier | DPI, IDS/IPS, filtrage d’URL, filtrage DNS | Suricata/Snort, Squid + SquidGuard, pfBlockerNG DNSBL |
Retenez surtout la ligne de fracture : jusqu’à la couche 4, le pare-feu décide seul, dans le noyau, à pleine vitesse. À partir de la couche 5, il lui faut un moteur d’inspection, du contexte, et souvent des certificats.
Couche 2 : le filtrage qu’on oublie
En mode routeur classique, la couche 2 sert surtout à décider sur quelle interface le paquet est arrivé. Une règle pfSense commence toujours par une interface (LAN, WAN, un VLAN) : c’est déjà de la couche 2 déguisée, puisque l’interface définit le domaine de broadcast.
Le VLAN, c’est la même chose : un tag 802.1Q dans l’en-tête Ethernet, que le pare-feu lit pour attribuer le paquet à une sous-interface logique. Quand on sépare un réseau invité d’un réseau serveurs, la décision de sécurité la plus forte est prise avant même de regarder une IP : les deux VLAN n’ont juste pas le droit de se parler, point.
Le cas où la couche 2 devient un vrai levier de filtrage, c’est le bridge transparent : le pare-feu est posé au milieu d’un segment L2, sans IP, sans NAT, et filtre le trafic entre deux ports comme le ferait un switch qui aurait des règles. pfSense sait le faire — un bridge y regroupe plusieurs interfaces dans un même domaine de broadcast, et la différence avec un switch matériel est précisément qu’on peut appliquer des règles pf entre les membres.
Attention à la nuance pfSense : le filtrage explicite sur les attributs d’en-tête Ethernet (les Ethernet Rules) est une fonctionnalité pfSense Plus à partir de 23.05, désactivée par défaut, à activer dans System > Advanced. En pfSense CE, vous n’avez pas ce tab. C’est le genre de détail qui fait perdre une soirée quand on suit un tuto sans vérifier l’édition.
Et pour dire la vérité : le filtrage MAC en tant que mesure de sécurité, c’est du théâtre. Deux commandes suffisent à changer une MAC. Comme je l’écrivais dans l’article couche 2, la MAC identifie, elle n’authentifie pas. La vraie sécurité L2 s’appelle 802.1X, DHCP snooping et Dynamic ARP Inspection — et ça se joue sur le switch, pas sur le pare-feu.
Couche 3 : le packet filtering, l’ancêtre toujours vivant
C’est la couche du pare-feu « historique » : on lit l’IP source, l’IP destination, le protocole (TCP/UDP/ICMP/GRE/ESP…), et on décide. Un pare-feu purement L3 est stateless : chaque paquet est jugé isolément, sans mémoire de ce qui précède.
Personne ne fait plus ça pour du filtrage général — mais la couche 3 reste omniprésente :
- Les aliases. Sous pfSense, un alias nomme un ensemble d’IP (ou de ports, ou de réseaux) pour ne pas écrire 40 règles. C’est la brique d’organisation de base d’un jeu de règles lisible.
- Le GeoIP et les listes de réputation. pfBlockerNG bloque des pays ou des ASN entiers sans jamais regarder au-dessus de la couche 3. C’est brutal, c’est efficace, ça coûte trois fois rien.
- L’anti-spoofing. Un paquet prétendant venir de 192.168.10.5 mais arrivant par le port WAN est incohérent avec la table de routage : on le jette.
pfle fait via l’optionantispoof— c’est l’uRPF vu dans l’article couche 3. - Le NAT. Réécrire les en-têtes L3 (et L4 pour le PAT), c’est de la manipulation de couche 3 pure.
- ICMP. Le protocole le plus maltraité de l’histoire du firewalling. Bloquer tout ICMP en sortie casse la découverte de MTU (Path MTU Discovery) et vous offre des sessions TLS qui gèlent à mi-chemin sans aucun log. Laissez passer
type 3 code 4— le détail est développé dans l’article couche 3.
C’est aussi ici que se joue une bonne partie de la protection anti-DoS de base : des compteurs L3/L4 (X paquets par seconde depuis une source, on jette). Simple, rapide — et redoutablement générateur de faux positifs si le seuil est mal calibré, mais c’est une autre histoire.
Couche 4 : l’état, le vrai cœur du réacteur
Si vous ne deviez retenir qu’une couche, c’est celle-là.
Un pare-feu stateful ne se contente pas de lire les ports. Il maintient une table d’états : pour chaque flux, il mémorise le quintuplet (IP src, port src, IP dst, port dst, protocole), l’état de la connexion, et un timer. La conséquence est énorme :
Vous n’écrivez que des règles dans un sens. Le trafic retour est autorisé automatiquement parce qu’il correspond à un état existant. Un paquet qui arrive sans état correspondant et sans règle qui l’autorise est jeté.
C’est ça qui rend un pare-feu utilisable. Sans état, il faudrait autoriser explicitement tous les ports hauts en entrée pour que vos utilisateurs puissent surfer — autrement dit, ne rien filtrer. C’est le prolongement direct de ce qu’on a vu dans l’article couche 4 sur les états TCP.
Concrètement :
# pfSense — voir la state table
pfctl -s state | grep 10.0.0.50
pfctl -s info # nombre d'états, searches, inserts, mismatchs
pf vous montre qui parle à qui, dans quel état, et pour combien de temps encore.
Le point qui piège tout le monde : quand vous modifiez une règle, les états déjà établis ne sont pas ré-évalués. Vous bloquez un flux, il continue de passer, vous cherchez une heure. La bonne réaction : vider les états concernés (pfctl -k avec un filtre) avant de conclure que la règle est mauvaise.
UDP mérite une mention : il n’y a pas d’état dans UDP. Le pare-feu en invente un, en créant un pseudo-état avec un timer court dès qu’il voit un paquet sortant. C’est fragile, et c’est pour ça que les protocoles UDP asymétriques (VoIP, jeux, certains VPN) donnent tant de sueurs froides — le lien avec la nature « sans connexion » d’UDP décrite en couche 4 est direct.
Couches 5 et 6 : le mur du TLS
C’est ici que le modèle OSI cesse d’être une abstraction pédagogique et devient un problème opérationnel très concret. Et c’est le prolongement exact de ce qu’on disait des couches fantômes : TLS fait le travail de la couche présentation sans appartenir vraiment à une couche.
Aujourd’hui, l’écrasante majorité du trafic est chiffrée. Au-dessus de la couche 4, le pare-feu voit… du bruit. Sauf à trois endroits, dans le ClientHello du handshake TLS, qui lui est en clair :
- Le SNI (Server Name Indication) — le nom de domaine demandé.
- Le certificat serveur — son CN, son SAN, son émetteur, sa validité.
- La version TLS et les cipher suites négociées, plus l’ALPN.
D’où deux stratégies :
Inspection par SNI/certificat. Le pare-feu lit le SNI et le certificat, applique une décision, et laisse le tunnel intact. C’est peu coûteux, ça ne casse rien, ça ne nécessite aucune CA déployée sur les postes. Ça permet de bloquer facebook.com ou de catégoriser une URL au niveau du domaine. Mais ça ne voit pas l’URL complète, pas le contenu, pas le fichier téléchargé. Sous pfSense, on l’obtient par assemblage : HAProxy pour du filtrage SNI, ou les règles SNI de Suricata.
Inspection profonde (« deep inspection », SSL/TLS interception). Le pare-feu se fait passer pour le serveur auprès du client, et pour le client auprès du serveur. Il déchiffre, inspecte, rechiffre. Il voit tout. Le prix à payer :
- Il faut déployer la CA du pare-feu sur tous les postes (GPO, MDM…).
- Le certificate pinning des applications modernes (Chrome update, apps mobiles, agents cloud) va casser. Il faudra des exemptions.
- Le CPU s’effondre. C’est le poste de dépense n°1 dès qu’on l’active.
- Et juridiquement, en entreprise, ça ne s’improvise pas : information des utilisateurs, exclusion des catégories santé/banque/RH.
Sous pfSense, il n’y a pas d’interception TLS « clé en main » : on y arrive par assemblage, avec Squid en proxy explicite et SSL bump. Ça marche, mais on assemble soi-même — ce qui est à la fois la force (on comprend chaque brique) et la contrainte (on est l’intégrateur) de l’approche libre.
Note ESNI/ECH : le chiffrement du ClientHello (Encrypted Client Hello) est en train de faire disparaître le SNI en clair. Le jour où il sera généralisé, le filtrage par SNI mourra, et il ne restera que le DNS et le déchiffrement complet. À surveiller de près.
Couche 7 : là où on paie vraiment
Filtrer en couche 7, c’est regarder le contenu, une fois tout le reste épluché (et déchiffré, le cas échéant).
Ce que ça permet, et que rien en dessous ne permet :
- Filtrage d’URL : bloquer
example.com/malware/mais autoriserexample.com/support/. Sous pfSense, c’est Squid + SquidGuard. - IDS/IPS : détecter une tentative d’exploitation dans le payload. C’est Suricata (ou Snort) en mode inline ou legacy, avec les règles ETOpen + Snort GPLv2 comme socle gratuit.
- Filtrage DNS : intercepter la requête et répondre à la place du serveur. C’est le principe de pfBlockerNG DNSBL — et c’est le plus rentable de tous les filtrages L7 : quasi gratuit en CPU, énorme en efficacité, parce qu’il tue le flux avant même qu’une session TCP existe. C’est exactement la mécanique décrite dans l’article couche 7 sur le DNS : on agit au niveau de la résolution de nom, tout en haut de la pile, pour ne jamais laisser le reste s’établir.
Un montage classique et solide sous pfSense consiste à empiler pfBlockerNG d’abord (GeoIP en L3, DNSBL en L7), Suricata ensuite (inspection de payload), les règles pf en dernier (l’ossature stateful). Chaque couche filtre ce qui la concerne, à son coût.
Le vrai pipeline n’est pas 1 → 7
Voilà le point que je voulais amener depuis le début, et celui qui distingue une compréhension scolaire d’une compréhension opérationnelle.
Intuitivement, on imagine : le paquet arrive, on épluche la couche 2, puis 3, puis 4, puis 7, et à chaque étape on peut dire non. C’est faux.
Prenez un filtrage applicatif par IDS. Pour que Suricata reconnaisse qu’un flux est du BitTorrent, il faut qu’il ait laissé passer les premiers paquets de la session — sinon il n’a rien à analyser. La décision de blocage arrive donc après coup, sur une session déjà entamée. On ne bloque pas avant d’identifier — on interrompt une fois identifié.
C’est là que naissent les incompréhensions : « ma règle Suricata bloque BitTorrent mais je vois quand même du trafic dans les logs ». Bien sûr : les premiers paquets étaient nécessaires pour savoir que c’était BitTorrent.
Conséquence directe et contre-intuitive :
Une information de couche 7 (l’identité applicative) est nécessaire pour appliquer la décision — mais elle n’est disponible qu’APRÈS avoir laissé passer du trafic. Le pare-feu décide donc sur une session déjà entamée, pas sur le premier paquet.
Autre piège, plus vicieux : l’ordre des règles. pf évalue en last-match par défaut (la dernière règle qui matche gagne), là où beaucoup d’autres moteurs sont en first-match. Une règle trop large placée au mauvais endroit court-circuite votre intention. Le classique — et une source inépuisable de « ma règle ne matche pas ».
Les erreurs classiques
Filtrer trop haut ce qui se filtre en bas. Bloquer un pays via inspection applicative alors qu’un objet géographique en couche 3 (pfBlockerNG GeoIP) fait le travail pour 1 % du CPU. Toujours filtrer à la couche la plus basse qui suffit.
Croire que le port définit le service. N’importe quoi tourne sur 443 aujourd’hui. Une règle « autoriser TCP/443 » n’autorise pas « le web » : elle autorise tout ce que quelqu’un a réussi à emballer dans du TLS. C’est précisément la raison d’être de l’inspection applicative.
Bloquer tout ICMP. Vous cassez le PMTUD. Symptôme : petits paquets OK, gros paquets qui disparaissent, sessions qui gèlent. Diagnostic impossible si on ne connaît pas le mécanisme — voir l’article couche 3.
Oublier que les états ne sont pas ré-évalués. Vous modifiez une règle, rien ne change, vous concluez que la règle est mauvaise. Videz les états (pfctl -k).
Activer la deep inspection partout, d’un coup. Votre CPU explose, le pinning casse une dizaine d’applications, et vous passez la semaine à écrire des exemptions. Ça se déploie par périmètre, progressivement, avec les exemptions préparées avant.
Confondre pfSense CE et pfSense Plus. Les Ethernet Rules, l’ordre des fonctions, certains packages : les tutos ne précisent pas toujours. Vérifiez l’édition avant de chercher un menu qui n’existe pas.
Croire qu’un pare-feu dispense d’une architecture réseau. Le meilleur pare-feu du monde ne voit pas le trafic qui ne passe pas par lui. Si votre switch L3 route entre VLAN, votre pare-feu est aveugle sur ce trafic-là. La segmentation précède le filtrage.
Ce que je retiens
Le modèle OSI, quand on parle pare-feu, n’est pas un schéma de révision : c’est une grille de coût. Chaque couche supplémentaire épluchée achète de la finesse et se paie en CPU, en latence et en complexité opérationnelle. Un bon jeu de règles, c’est un jeu où chaque décision est prise à la couche la plus basse possible.
La deuxième leçon, moins confortable : le pipeline réel d’un pare-feu moderne viole allègrement l’ordre des couches. Il consulte une table d’états (L4) avant de regarder une règle, il laisse passer des paquets pour identifier une application (L7) avant de la bloquer. Le modèle OSI décrit ce que l’appareil lit ; il ne décrit pas dans quel ordre il décide. Confondre les deux, c’est la source de la moitié des tickets « ma règle ne fonctionne pas ».
Et la troisième, qui referme la série OSI : chaque couche de la pile qu’on a parcourue, du câble à l’application, correspond à un point de décision possible dans un pare-feu. Comprendre le modèle OSI, ce n’est pas réviser pour un examen — c’est savoir, face à un flux à bloquer, à quel étage poser le filtre. C’est toute la série condensée en une compétence.
Sources et références
- pfSense — documentation officielle (Netgate) : docs.netgate.com/pfsense
pf— packet filter d’OpenBSD (la référence du moteur sous pfSense) : openbsd.org/faq/pf- Suricata — moteur IDS/IPS : docs.suricata.io
- pfBlockerNG (GeoIP, DNSBL) : docs.netgate.com — pfBlockerNG
- RFC 8446 — TLS 1.3 (le SNI, le ClientHello) : datatracker.ietf.org/doc/rfc8446
- RFC 9293 — TCP (les états, le stateful) : datatracker.ietf.org/doc/rfc9293
- Encrypted Client Hello (le futur du SNI) : datatracker.ietf.org — TLS ECH
- Pour situer chaque couche : la série OSI complète sur Aperture Zone.
Cet article referme la série sur le modèle OSI : après avoir monté la pile couche par couche, on a vu comment un seul appareil la parcourt tout entière pour décider.