<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>Crowdsec - Balise - arleo.eu</title>
        <link>https://www.arleo.eu/tags/crowdsec/</link>
        <description>Crowdsec - Balise - arleo.eu</description>
        <generator>Hugo -- gohugo.io</generator><language>fr</language><lastBuildDate>Mon, 25 May 2026 20:51:17 &#43;0200</lastBuildDate><atom:link href="https://www.arleo.eu/tags/crowdsec/" rel="self" type="application/rss+xml" /><item>
    <title>Postmortem — CrowdSec AppSec : faux positif heuristique sur Sonarr/Radarr</title>
    <link>https://www.arleo.eu/posts/postmortem-crowdsec-appsec-false-positive-sonarr/</link>
    <pubDate>Mon, 25 May 2026 20:51:17 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/postmortem-crowdsec-appsec-false-positive-sonarr/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/postmortem-crowdsec-appsec-false-positive-sonarr-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="résumé">Résumé</h2>
<p>Le <strong>25 mai 2026 vers 22h02 (heure locale)</strong>, Sonarr et Radarr sont devenus totalement inaccessibles depuis l&rsquo;IP maison (<code>82.XX.XX.XX</code>), retournant <strong>403</strong> sur toutes les URLs y compris <code>/login</code>. Le service était pourtant opérationnel. Le diagnostic initial suspectait les récents déploiements du refactor <code>crowdsec-cf-sync</code> — la cause réelle est un <strong>faux positif heuristique CrowdSec AppSec</strong>.</p>
<hr>
<h2 id="timeline">Timeline</h2>
<table>
  <thead>
      <tr>
          <th>Heure (locale)</th>
          <th>Événement</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>~22h00</td>
          <td>Cookie de session Sonarr expiré côté navigateur</td>
      </tr>
      <tr>
          <td>22h02:31</td>
          <td>Le navigateur charge la bibliothèque Sonarr → tente de charger 20+ <code>/MediaCover/*.jpg</code> simultanément</td>
      </tr>
      <tr>
          <td>22h02:31</td>
          <td>Sonarr retourne 302 → <code>/login</code> pour chaque image (session invalide)</td>
      </tr>
      <tr>
          <td>22h02:34</td>
          <td>La connexion SignalR WebSocket s&rsquo;établit (101) via <code>access_token</code> dans l&rsquo;URL</td>
      </tr>
      <tr>
          <td>~22h05</td>
          <td>CrowdSec AppSec déclenche la règle heuristique <code>http-probing</code> : rafale de requêtes échouées depuis la même IP</td>
      </tr>
      <tr>
          <td>22h11:37</td>
          <td>Toutes les requêtes de <code>82.XX.XX.XX</code> retournent 403 — <code>cs_reason=heuristic</code> dans les logs nginx</td>
      </tr>
      <tr>
          <td>22h13:34</td>
          <td>Même <code>/login</code> bloqué — l&rsquo;IP ne peut plus s&rsquo;authentifier</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="cause-racine">Cause racine</h2>
<p>CrowdSec AppSec maintient un <strong>état heuristique en mémoire</strong>, distinct des décisions LAPI. Lorsque le navigateur tente de charger simultanément de nombreuses ressources et reçoit des 302/403 de l&rsquo;application upstream (Sonarr), AppSec interprète cette rafale d&rsquo;échecs comme du sondage agressif (<code>http-probing</code>) et bloque l&rsquo;IP source.</p>]]></description>
</item>
<item>
    <title>CrowdSec AppSec &#43; OpenResty : WAF moderne sans ModSecurity</title>
    <link>https://www.arleo.eu/posts/crowdsec-appsec-openresty/</link>
    <pubDate>Mon, 18 May 2026 00:07:11 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/crowdsec-appsec-openresty/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/crowdsec-appsec-openresty-featured.jpg" referrerpolicy="no-referrer">
            </div><p>Après des années avec ModSecurity + OWASP CRS sur nginx, j&rsquo;ai migré arleo.eu vers une stack plus moderne : <strong>CrowdSec AppSec sur OpenResty</strong>. Le résultat est une architecture WAF inline mieux intégrée, plus facile à maintenir, et plus cohérente avec le reste de la stack de sécurité.</p>
<h2 id="pourquoi-abandonner-modsecurity-">Pourquoi abandonner ModSecurity ?</h2>
<p>ModSecurity v2 est en fin de vie active. Le maintien des règles OWASP CRS sur nginx classique génère de la friction : faux positifs fréquents, logs difficiles à corréler avec CrowdSec, et une configuration dispersée entre plusieurs outils sans vision unifiée.</p>]]></description>
</item>
<item>
    <title>Audit sécurité NUC : ModSecurity supprimé, 500 MB récupérés</title>
    <link>https://www.arleo.eu/posts/audit-securite-modsecurity-crowdsec/</link>
    <pubDate>Thu, 14 May 2026 05:31:23 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/audit-securite-modsecurity-crowdsec/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/audit-securite-modsecurity-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="-en-bref">⚡ En bref</h2>
<p>Un audit de la stack sécurité du NUC révèle une <strong>double inspection WAF redondante</strong> : ModSecurity + OWASP CRS chargent 11 872 règles en mémoire malgré <code>SecRuleEngine Off</code>, en parallèle d&rsquo;un CrowdSec AppSec déjà actif et couvrant le même périmètre. Après suppression du module nginx ModSecurity et 5 autres correctifs ciblés, nginx passe de <strong>~520 MB à ~27 MB PSS</strong>. Sécurité identique, empreinte divisée par 20.</p>
<hr>
<h2 id="-architecture-avant-audit">🏗️ Architecture avant audit</h2>
<p>La stack sécurité reposait sur six couches empilées :</p>]]></description>
</item>
<item>
    <title>Pipeline de logs CrowdSec avec Vector : filtrer le bruit et capturer les vrais bans</title>
    <link>https://www.arleo.eu/posts/crowdsec-vector-pipeline/</link>
    <pubDate>Wed, 15 Apr 2026 19:01:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/crowdsec-vector-pipeline/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/crowdsec-vector-pipeline-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="-en-bref">⚡ En bref</h2>
<p>Le pipeline Vector initial inondait BetterStack de ~500 events/24h, dont 434 pulls CAPI sans valeur de supervision locale. Ce travail reconfigure le filtre Vector pour ne garder que les bans à haute valeur (<code>cscli</code>) et corrige un angle mort majeur : les bans effectifs du bouncer nginx-lua n&rsquo;apparaissaient nulle part dans BetterStack.</p>
<h2 id="-pourquoi">🧠 Pourquoi</h2>
<p>La stack de sécurité repose sur trois composants qui travaillent ensemble :</p>
<ul>
<li><strong>nginx</strong> avec le bouncer lua CrowdSec (<code>lua-resty-crowdsec</code>) qui bloque les requêtes en temps réel</li>
<li><strong>CrowdSec</strong> pour la détection et la gestion des décisions de ban</li>
<li><strong>Vector</strong> qui centralise les logs vers BetterStack pour la supervision</li>
</ul>
<p>Après avoir mis en place le pipeline initial, deux problèmes sont apparus rapidement. D&rsquo;abord, le signal était noyé dans le bruit : sur 500 events/24h, 434 venaient du pull CAPI communautaire horaire et 66 des listes tierces — ni les uns ni les autres ne représentent une menace détectée sur <em>cette</em> infrastructure. Ensuite, les bans effectifs du bouncer lua (blocages en temps réel dans nginx) n&rsquo;apparaissaient nulle part dans BetterStack, ce qui créait un angle mort sur l&rsquo;activité de sécurité réelle.</p>]]></description>
</item>
<item>
    <title>Documentation Infrastructure</title>
    <link>https://www.arleo.eu/documentation/</link>
    <pubDate>Sun, 12 Apr 2026 21:24:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/documentation/</guid>
    <description><![CDATA[<h2 id="1-architecture-de-sécurité-10-couches">1. Architecture de sécurité (10 couches)</h2>
<table>
  <thead>
      <tr>
          <th>#</th>
          <th>Couche</th>
          <th>Technologie</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>DNS</td>
          <td>DNSSEC ECDSA P256-SHA256</td>
      </tr>
      <tr>
          <td>2</td>
          <td>CDN + WAF Cloud</td>
          <td>Cloudflare WAF + DDoS + AI Crawl Control</td>
      </tr>
      <tr>
          <td>3</td>
          <td>Réseau</td>
          <td>CrowdSec nftables Bouncer</td>
      </tr>
      <tr>
          <td>4</td>
          <td>Firewall</td>
          <td>Netgear PR60X SPI</td>
      </tr>
      <tr>
          <td>5</td>
          <td>WAF Local</td>
          <td>ModSecurity + OWASP CRS 4.x</td>
      </tr>
      <tr>
          <td>6</td>
          <td>IDS/IPS</td>
          <td>CrowdSec Agent + scénarios SSH/HTTP</td>
      </tr>
      <tr>
          <td>7</td>
          <td>HTTPS</td>
          <td>TLS 1.3 + HSTS preload</td>
      </tr>
      <tr>
          <td>8</td>
          <td>DNS-TLS</td>
          <td>DoH port 853</td>
      </tr>
      <tr>
          <td>9</td>
          <td>Application</td>
          <td>Grav CMS + CSP + Secure cookies</td>
      </tr>
      <tr>
          <td>10</td>
          <td>Monitoring</td>
          <td>BetterStack + CrowdSec poller + Vector</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="2-crowdsec--cloudflare-sync-crowdsec-cf-syncpy">2. CrowdSec → Cloudflare Sync (<code>crowdsec-cf-sync.py</code>)</h2>
<p><strong>Emplacement :</strong> <code>/usr/local/bin/crowdsec-cf-sync.py</code>
<strong>Service :</strong> <code>crowdsec-cf-sync.service</code>
<strong>Logs :</strong> <code>/var/log/crowdsec/cf-sync.log</code></p>]]></description>
</item>
<item>
    <title>Scripts Infrastructure</title>
    <link>https://www.arleo.eu/scripts/</link>
    <pubDate>Sun, 12 Apr 2026 21:24:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/scripts/</guid>
    <description><![CDATA[<h2 id="1-crowdsec-cf-syncpy">1. crowdsec-cf-sync.py</h2>
<p><strong>Emplacement :</strong> <code>/usr/local/bin/crowdsec-cf-sync.py</code>
<strong>Service systemd :</strong> <code>crowdsec-cf-sync.service</code>
<strong>Logs :</strong> <code>/var/log/crowdsec/cf-sync.log</code></p>
<h3 id="installation">Installation</h3>
<div class="code-block code-line-numbers open" data-start="0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="Copier dans le presse-papiers"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cp crowdsec-cf-sync.py /usr/local/bin/
</span></span><span class="line"><span class="cl">chmod +x /usr/local/bin/crowdsec-cf-sync.py
</span></span><span class="line"><span class="cl">systemctl <span class="nb">enable</span> crowdsec-cf-sync
</span></span><span class="line"><span class="cl">systemctl start crowdsec-cf-sync</span></span></code></pre></div></div>
<h3 id="fonctionnalités">Fonctionnalités</h3>
<ul>
<li>Synchronise les bans CrowdSec actifs → Cloudflare IP Access Rules (tag <code>crowdsec-local-ban</code>)</li>
<li>Reporte les IPs bannies → AbuseIPDB (fenêtre 48h, dédupliqué)</li>
<li><strong>Escalade récidivistes</strong> : 1er ban CrowdSec gère | 2ème → 24h | 3ème+ → 7j (fenêtre 7j)</li>
<li><strong>ModSecurity</strong> score ≥ 5 → ban CF immédiat 2h (tag <code>modsec-ban</code>) + report AbuseIPDB</li>
<li><strong>Ban /24</strong> automatique : 2+ IPs du même bloc en 7j → ban CF + CrowdSec 24h (tag <code>crowdsec-cidr-ban</code>)</li>
</ul>
<h3 id="bugs-corrigés-avril-2026">Bugs corrigés (avril 2026)</h3>
<ul>
<li><code>cs_origin</code> vs <code>origin</code> dans <code>get_recent_local_bans()</code> — le champ JSON s&rsquo;appelle <code>cs_origin</code></li>
<li>Pagination API REST <code>/v1/decisions?limit=1000</code> rate les bans <code>cscli</code> → remplacé par <code>cscli decisions list --origin</code></li>
<li><code>Items</code> → <code>items</code> (minuscule) dans le parsing JSON de la allowlist CrowdSec</li>
</ul>
<blockquote>
<p>⚠️ <strong>Important</strong> : les vrais tokens (<code>CF_API_TOKEN</code>, <code>CF_ZONE_ID</code>, <code>CS_API_KEY</code>, <code>ABUSEIPDB_KEY</code>) doivent être stockés dans <code>/etc/secrets/</code> avec <code>chmod 600</code> et chargés via variables d&rsquo;environnement, pas hardcodés dans le script. Les valeurs <code>VOTRE_*</code> ci-dessous sont des placeholders.</p>]]></description>
</item>
<item>
    <title>Harmonisation des logs nginx et CrowdSec dans BetterStack via Vector</title>
    <link>https://www.arleo.eu/posts/vector-logs-harmonisation-betterstack/</link>
    <pubDate>Fri, 10 Apr 2026 21:04:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/vector-logs-harmonisation-betterstack/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/vector-logs-harmonisation-betterstack-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="-en-bref">⚡ En bref</h2>
<p>Deux problèmes coexistaient dans BetterStack : les logs <code>mcp-oauth.access.log</code> arrivaient en JSON brut illisible, et les logs CrowdSec produisaient des doublons visuels. Ce travail uniformise tous les logs pour qu&rsquo;ils s&rsquo;affichent comme des tags cliquables structurés, avec timestamps corrects et sans champs parasites.</p>
<h2 id="-pourquoi">🧠 Pourquoi</h2>
<p>BetterStack affiche les logs sous forme de tags surlignés cliquables dans le Live Tail lorsque les champs JSON sont correctement structurés. Avant ce travail, l&rsquo;observation était dégradée sur deux fronts :</p>]]></description>
</item>
<item>
    <title>Automatiser le ban d&#39;IPs avec Cloudflare WAF, CrowdSec et AbuseIPDB</title>
    <link>https://www.arleo.eu/posts/crowdsec-cloudflare-waf-autoban/</link>
    <pubDate>Fri, 10 Apr 2026 00:23:00 &#43;0200</pubDate>
    <author>Jmr</author>
    <guid>https://www.arleo.eu/posts/crowdsec-cloudflare-waf-autoban/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/crowdsec-cloudflare-waf-autoban-featured.jpg" referrerpolicy="no-referrer">
            </div><h2 id="-en-bref">⚡ En bref</h2>
<p>Le monitoring passif ne suffit pas. Ce pipeline automatise la <strong>fermeture de la boucle en moins de 5 minutes</strong> entre une attaque détectée par Cloudflare WAF et le ban effectif de l&rsquo;IP dans CrowdSec, sa synchronisation vers Cloudflare et son signalement sur AbuseIPDB. Un script Python poll l&rsquo;API GraphQL Cloudflare toutes les 5 minutes, applique un seuil de 3 hits, et déclenche le ban avec escalade récidiviste.</p>]]></description>
</item>
</channel>
</rss>
