<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hyperscan on Mook’s Lab Chronicles</title><link>https://blog.homeblack.fr/tags/hyperscan/</link><description>Recent content in Hyperscan on Mook’s Lab Chronicles</description><generator>Hugo -- gohugo.io</generator><language>fr-FR</language><lastBuildDate>Mon, 24 Aug 2026 15:20:00 +0200</lastBuildDate><atom:link href="https://blog.homeblack.fr/tags/hyperscan/index.xml" rel="self" type="application/rss+xml"/><item><title>J’ai enfin activé Hyperscan sur mes deux OPNsense</title><link>https://blog.homeblack.fr/p/hyperscan-suricata-opnsense/</link><pubDate>Mon, 24 Aug 2026 15:20:00 +0200</pubDate><guid>https://blog.homeblack.fr/p/hyperscan-suricata-opnsense/</guid><description>&lt;img src="https://blog.homeblack.fr/p/hyperscan-suricata-opnsense/cover.png" alt="Featured image of post J’ai enfin activé Hyperscan sur mes deux OPNsense" /&gt;&lt;p&gt;Tout est parti d’un article publié sur le blog de Suricata : &lt;a class="link" href="https://suricata.io/2025/10/07/faster-suricata-startups-with-hyperscan-caching/" target="_blank" rel="noopener"
&gt;&lt;em&gt;Faster Suricata startups with Hyperscan caching&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Le sujet était le cache MPM (&lt;em&gt;Multi-Pattern Matching&lt;/em&gt;) introduit avec Suricata 8. Au lieu de recompiler toutes les bases de motifs Hyperscan à chaque démarrage ou rechargement des règles, Suricata peut les conserver sur disque et les réutiliser. L’article annonçait un temps de démarrage réduit jusqu’à 50 %.&lt;/p&gt;
&lt;p&gt;En le lisant, je me suis surtout posé une question beaucoup plus basique : est-ce qu’Hyperscan tournait réellement sur mes firewalls ?&lt;/p&gt;
&lt;p&gt;La réponse était non.&lt;/p&gt;
&lt;p&gt;Suricata fonctionnait déjà sur mes deux OPNsense, les événements remontaient bien dans VictoriaLogs et mon cluster HA faisait son travail. Mais le moteur de recherche de motifs capable de profiter des instructions vectorielles du processeur n’était pas actif.&lt;/p&gt;
&lt;p&gt;Le verrou ne se trouvait pas vraiment dans Suricata. Mes deux VM utilisaient encore le modèle de CPU générique &lt;code&gt;kvm64&lt;/code&gt;, pratique pour la compatibilité, mais trop conservateur pour exposer les instructions que je voulais utiliser. Avant de jouer avec le cache, il fallait donc commencer par activer le moteur lui-même.&lt;/p&gt;
&lt;h2 id="donner-le-bon-cpu-virtuel-à-suricata"&gt;Donner le bon CPU virtuel à Suricata
&lt;/h2&gt;&lt;p&gt;J’ai passé &lt;code&gt;fw-core-p1&lt;/code&gt; et &lt;code&gt;fw-core-p2&lt;/code&gt; en &lt;code&gt;x86-64-v3&lt;/code&gt;. FreeBSD voyait alors correctement AVX2, AES et FMA, et je pouvais enfin demander explicitement Hyperscan à Suricata :&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-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;cpu&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;x86-64-v3&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;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;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;opnsense_ids_mpm_algo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hs&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&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;Le &lt;code&gt;hs&lt;/code&gt; sélectionne Hyperscan comme moteur MPM. C’est la partie de Suricata qui cherche plusieurs motifs à la fois dans le trafic et écarte rapidement les signatures qui ne peuvent pas correspondre. La &lt;a class="link" href="https://docs.opnsense.org/manual/ips.html" target="_blank" rel="noopener"
&gt;documentation OPNsense&lt;/a&gt; le présente d’ailleurs comme le meilleur choix sur les plateformes compatibles.&lt;/p&gt;
&lt;p&gt;Le changement posait tout de même une question importante : mes hôtes Proxmox mélangent des processeurs Intel et AMD. J’ai donc fait migrer une VM de test d’Intel vers AMD, puis de nouveau vers Intel, avant de considérer &lt;code&gt;x86-64-v3&lt;/code&gt; comme un socle suffisamment portable chez moi.&lt;/p&gt;
&lt;p&gt;Je n’ai pas touché aux règles de placement HA. Les deux firewalls restent volontairement séparés sur deux hôtes différents.&lt;/p&gt;
&lt;h2 id="le-test-qui-comptait-vraiment"&gt;Le test qui comptait vraiment
&lt;/h2&gt;&lt;p&gt;Voir &lt;code&gt;mpm-algo = hs&lt;/code&gt; sur les deux nœuds était une bonne nouvelle, mais cela ne disait encore rien sur le comportement du cluster pendant une vraie bascule.&lt;/p&gt;
&lt;p&gt;J’ai donc laissé &lt;code&gt;p2&lt;/code&gt; reprendre les neuf VIP CARP. Pendant qu’il était MASTER avec Hyperscan actif, la sortie Internet continuait de fonctionner. Je n’ai observé aucune perte de paquets pendant le failover, avec une latence maximale de 13 ms.&lt;/p&gt;
&lt;p&gt;Après le test, la situation normale était revenue : &lt;code&gt;p1&lt;/code&gt; MASTER, &lt;code&gt;p2&lt;/code&gt; BACKUP et neuf VIP au bon endroit. Le moteur de détection avait changé sans perturber le cluster.&lt;/p&gt;
&lt;h2 id="seize-heures-plus-tard"&gt;Seize heures plus tard
&lt;/h2&gt;&lt;p&gt;Le premier contrôle montrait déjà Suricata autour de 356 à 359 Mio de mémoire, contre environ 548 Mio auparavant. J’ai laissé tourner avant de regarder de nouveau les compteurs.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mesure&lt;/th&gt;
&lt;th&gt;Après environ 16 heures&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU Suricata&lt;/td&gt;
&lt;td&gt;0 à 0,1 % sur les deux nœuds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mémoire sur P1&lt;/td&gt;
&lt;td&gt;233 Mio, soit −57,5 % par rapport au repère de 548 Mio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mémoire sur P2&lt;/td&gt;
&lt;td&gt;356 Mio, stable depuis le premier contrôle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capture sur P1&lt;/td&gt;
&lt;td&gt;51 044 239 paquets, 4 669 drops, soit 0,0091 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capture sur P2&lt;/td&gt;
&lt;td&gt;1 078 301 paquets, aucun drop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Événements TLS&lt;/td&gt;
&lt;td&gt;22 056 événements centralisés dans VictoriaLogs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Les 4 669 drops de capture observés sur &lt;code&gt;p1&lt;/code&gt; n’avaient pas augmenté depuis plus de deux heures lors du dernier relevé. Aucun drop Suricata n’apparaissait dans les échantillons contrôlés et la qualité de capture restait supérieure à 99,99 %.&lt;/p&gt;
&lt;p&gt;Surtout, l’enrichissement n’avait pas disparu au passage : 926 SNI, 370 empreintes JA4, 55 empreintes de certificats et 23 émetteurs distincts remontaient toujours dans VictoriaLogs.&lt;/p&gt;
&lt;p&gt;Ce n’est pas un benchmark. &lt;code&gt;p1&lt;/code&gt; et &lt;code&gt;p2&lt;/code&gt; n’ont ni le même rôle ni le même volume de trafic, et je ne vais pas attribuer toute la baisse à une seule option. La tendance observée reste néanmoins assez nette : CPU négligeable, mémoire en baisse et aucune dégradation visible de la détection ou du failover.&lt;/p&gt;
&lt;p&gt;La configuration est maintenant décrite dans Terraform et Ansible. Le plan Terraform ne montrait aucun drift, le second passage Ansible terminait avec &lt;code&gt;changed=0&lt;/code&gt;, et les sept tests du rôle passaient avec le &lt;em&gt;syntax-check&lt;/em&gt; et &lt;code&gt;ansible-lint&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Assez ironiquement, un article consacré au cache m’aura d’abord fait découvrir que je n’utilisais même pas le moteur. Le cache pourra venir ensuite. Pour l’instant, Hyperscan tourne enfin sur mes deux firewalls — et c’était déjà le vrai chantier.&lt;/p&gt;</description></item></channel></rss>