<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Pfsync on Mook’s Lab Chronicles</title><link>https://blog.homeblack.fr/tags/pfsync/</link><description>Recent content in Pfsync on Mook’s Lab Chronicles</description><generator>Hugo -- gohugo.io</generator><language>fr-FR</language><lastBuildDate>Sat, 15 Aug 2026 23:30:00 +0200</lastBuildDate><atom:link href="https://blog.homeblack.fr/tags/pfsync/index.xml" rel="self" type="application/rss+xml"/><item><title>J’ai doublé mon firewall pour pouvoir en éteindre un</title><link>https://blog.homeblack.fr/p/opnsense-ha-carp-fw-core-p1-fw-core-p2/</link><pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate><guid>https://blog.homeblack.fr/p/opnsense-ha-carp-fw-core-p1-fw-core-p2/</guid><description>&lt;img src="https://blog.homeblack.fr/p/opnsense-ha-carp-fw-core-p1-fw-core-p2/cover.png" alt="Featured image of post J’ai doublé mon firewall pour pouvoir en éteindre un" /&gt;&lt;p&gt;Mon premier OPNsense fonctionnait très bien. C’était justement le problème.&lt;/p&gt;
&lt;p&gt;Tout le cœur du réseau reposait sur &lt;code&gt;fw-core-p1&lt;/code&gt; : le LAN, huit VLANs, l’accès Internet et les routes entre mes différentes zones. Tant que la VM tournait, je n’avais aucune raison d’y penser. Dès qu’une mise à jour demandait un redémarrage, la question revenait : qu’est-ce qui reste accessible si ce firewall s’arrête ?&lt;/p&gt;
&lt;p&gt;Pas grand-chose.&lt;/p&gt;
&lt;p&gt;Je ne cherchais pas à transformer mon homelab en infrastructure bancaire. Je voulais simplement pouvoir maintenir un firewall sans couper volontairement tout ce qui passait derrière lui. C’est comme ça que &lt;code&gt;fw-core-p2&lt;/code&gt; est arrivé.&lt;/p&gt;
&lt;h2 id="une-seconde-vm-ne-fait-pas-encore-un-cluster"&gt;Une seconde VM ne fait pas encore un cluster
&lt;/h2&gt;&lt;p&gt;Le plus facile aurait été de cloner &lt;code&gt;fw-core-p1&lt;/code&gt;, de démarrer la copie et d’appeler ça de la haute disponibilité. Deux firewalls mal coordonnés savent surtout produire deux fois plus de problèmes.&lt;/p&gt;
&lt;p&gt;J’ai donc commencé par leur donner la même forme. Les deux VM vivent sur deux nœuds Proxmox différents et possèdent exactement le même ordre d’interfaces : le WAN, le LAN, les huit VLANs du homelab, puis une dernière interface réservée à la synchronisation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pve-forum pve-fuji
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fw-core-p1 fw-core-p2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; MASTER ─── VLAN 999 SYNC ─── BACKUP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ pfsync │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ XML-RPC │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └────── 9 VIP CARP partagées ──┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Cette symétrie n’est pas seulement jolie dans Terraform. &lt;code&gt;pfsync&lt;/code&gt; associe les états aux interfaces : si leur ordre ou leur nom diffère entre les deux machines, la réplication ne raconte plus la même histoire des deux côtés.&lt;/p&gt;
&lt;h2 id="carp-pfsync-et-xml-rpc-ne-font-pas-le-même-travail"&gt;CARP, pfsync et XML-RPC ne font pas le même travail
&lt;/h2&gt;&lt;p&gt;J’avais tendance à ranger tout cela dans la boîte « HA ». En pratique, trois mécanismes distincts coopèrent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CARP&lt;/strong&gt; (&lt;em&gt;Common Address Redundancy Protocol&lt;/em&gt;) détermine quel firewall porte les adresses IP virtuelles. Les machines du réseau utilisent ces VIP comme passerelles et n’ont pas besoin de savoir si &lt;code&gt;p1&lt;/code&gt; ou &lt;code&gt;p2&lt;/code&gt; répond derrière.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;pfsync&lt;/strong&gt; réplique la table d’états. Quand &lt;code&gt;p2&lt;/code&gt; reprend le trafic, il connaît déjà les connexions suivies par &lt;code&gt;p1&lt;/code&gt; au lieu de repartir avec une feuille blanche.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;XML-RPC&lt;/strong&gt; synchronise la configuration depuis le primaire : règles, alias, NAT et objets partagés. Le second nœud reste ainsi un vrai pair, pas une vieille copie que j’espère encore correcte six mois plus tard.&lt;/p&gt;
&lt;p&gt;La &lt;a class="link" href="https://docs.opnsense.org/manual/how-tos/carp.html" target="_blank" rel="noopener"
&gt;documentation HA d’OPNsense&lt;/a&gt; recommande justement une interface dédiée à &lt;code&gt;pfsync&lt;/code&gt;. J’ai appliqué ce principe avec le VLAN 999, utilisé également pour la synchronisation de configuration.&lt;/p&gt;
&lt;p&gt;Dans Terraform, ce choix tient dans quelques lignes :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# vtnet10 -&amp;gt; SYNC (pfsync + xmlrpc HA)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;network_device&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; bridge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;fw_core_lan_bridge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; vlan_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;fw_core_sync_vlan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;virtio&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Ce petit &lt;code&gt;vtnet10&lt;/code&gt; est pourtant l’une des pièces les plus importantes du montage. Le trafic utilisateur et les échanges qui permettent au cluster de rester cohérent ne se disputent pas la même interface logique.&lt;/p&gt;
&lt;h2 id="le-moment-où-neuf-vip-ont-changé-de-côté"&gt;Le moment où neuf VIP ont changé de côté
&lt;/h2&gt;&lt;p&gt;Une interface verte dans OPNsense ne prouve pas grand-chose. Le cluster est devenu réel le jour où j’ai placé &lt;code&gt;fw-core-p1&lt;/code&gt; en maintenance et regardé &lt;code&gt;fw-core-p2&lt;/code&gt; reprendre les neuf VIP.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fw-core-p1 : BACKUP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fw-core-p2 : MASTER
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VIP CARP : 9/9 sur p2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le DNS continuait de répondre et mes routes applicatives restaient accessibles. En quittant le mode maintenance, &lt;code&gt;p1&lt;/code&gt; a repris son rôle par préemption et &lt;code&gt;p2&lt;/code&gt; est retourné attendre en secours.&lt;/p&gt;
&lt;p&gt;C’est un test très simple, mais il change complètement la confiance que j’accorde au montage. Avant lui, j’avais deux VM configurées pour faire du CARP. Après lui, j’avais un cluster que je pouvais réellement utiliser pendant une intervention.&lt;/p&gt;
&lt;h2 id="la-haute-disponibilité-synchronise-aussi-les-erreurs"&gt;La haute disponibilité synchronise aussi les erreurs
&lt;/h2&gt;&lt;p&gt;Le piège le plus intéressant est arrivé plus tard. Une VIP utilisait un pair CARP unicast propre à &lt;code&gt;p1&lt;/code&gt;. XML-RPC a parfaitement synchronisé cette valeur vers &lt;code&gt;p2&lt;/code&gt;, qui s’est alors mis à envoyer ses annonces… à sa propre adresse.&lt;/p&gt;
&lt;p&gt;La synchronisation n’était pas cassée. Elle exécutait fidèlement une configuration qui n’aurait pas dû être identique sur les deux nœuds.&lt;/p&gt;
&lt;p&gt;J’ai raconté cette petite surprise dans &lt;a class="link" href="https://blog.homeblack.fr/p/revision-cluster-opnsense/" &gt;ma révision du cluster OPNsense&lt;/a&gt;. Elle m’a rappelé qu’un cluster ne rend pas une configuration correcte par magie. Il propage aussi très efficacement les mauvaises idées.&lt;/p&gt;
&lt;p&gt;Le retour au multicast CARP a supprimé cette exception locale et rendu les deux configurations réellement partageables. Depuis, mon test ne consiste plus seulement à vérifier que les deux firewalls affichent du vert : je provoque la bascule et je contrôle ce qui continue à fonctionner.&lt;/p&gt;
&lt;h2 id="ce-que-ce-second-firewall-a-réellement-changé"&gt;Ce que ce second firewall a réellement changé
&lt;/h2&gt;&lt;p&gt;Je n’ai pas supprimé tous les points de panne. Les deux VM dépendent toujours du réseau physique, des bridges Proxmox et de ce qui se trouve en amont. La haute disponibilité du firewall ne rend pas magiquement le reste du homelab redondant.&lt;/p&gt;
&lt;p&gt;Elle a en revanche retiré un blocage très concret : je peux éteindre un OPNsense sans considérer la coupure comme une étape normale de la maintenance.&lt;/p&gt;
&lt;p&gt;Le bénéfice n’est pas spectaculaire quand tout va bien. &lt;code&gt;fw-core-p2&lt;/code&gt; passe l’essentiel de son temps en BACKUP, ce qui est exactement ce que je lui demande. Sa valeur apparaît quand je mets à jour &lt;code&gt;p1&lt;/code&gt;, quand je redémarre une VM ou quand je veux vérifier une modification sans jouer toute la connectivité du homelab sur un seul clic.&lt;/p&gt;
&lt;p&gt;Au fond, j’ai doublé mon firewall pour pouvoir enfin en éteindre un sereinement. C’était tout le projet.&lt;/p&gt;</description></item></channel></rss>