Aller au contenu

Blocklists IP

Blocklists IP est une intégration de NGX OPS permettant de mettre en place un blocage ou une Challenge HTTP basé sur des adresses IP en utilisant la directive geo de Nginx.

Les adresses IP provenant des différentes listes sont agrégées et dédupliquées avant d'être intégrées à la configuration Nginx.

Les listes

Les listes d'adresses IP doivent être accessibles depuis une URL et respecter le format suivant, avec une adresse IP par ligne :

1.1.1.1
8.8.8.8
9.9.9.9

Il existe différentes listes communautaires disponibles sur Internet, notamment :

Afin d'optimiser la configuration, les différentes listes sont automatiquement agrégées et dédupliquées.

Il existe également des listes intégrés basés sur :

Configuration de base des listes

Pour configurer les listes, rendez-vous dans : ADMINISTRATION → Configuration → Blocklists IP

Dans la zone de saisie, renseignez la configuration souhaitée, puis cliquez sur Enregistrer.

Exemple 1 : une seule liste

L'exemple suivant utilise uniquement la liste Data-Shield et effectue une mise à jour toutes les six heures :

enable: true
interval_cron: "0 */6 * * *"
block_action: deny_403
hit_logging_enable: true
hit_logging_method: dedicated
sources:
  - name: datashield
    url: "https://raw.githubusercontent.com/duggytuxy/Data-Shield_IPv4_Blocklist/refs/heads/main/prod_data-shield_ipv4_blocklist.txt"
    enable: true

Exemple 2 : plusieurs listes

Il est également possible d'utiliser plusieurs sources simultanément. Dans cet exemple, les listes Data-Shield et GreenSnow sont utilisées :

enable: true
interval_cron: "0 */6 * * *"
block_action: drop_444
hit_logging_enable: true
hit_logging_method: dedicated
sources:
  - name: datashield
    url: "https://raw.githubusercontent.com/duggytuxy/Data-Shield_IPv4_Blocklist/refs/heads/main/prod_data-shield_ipv4_blocklist.txt"
    enable: true

  - name: greensnow
    url: "https://blocklist.greensnow.co/greensnow.txt"
    enable: true

Chaque source possède son propre nom, son URL et un paramètre enable permettant de l'activer ou de la désactiver.

Actions de blocage

Le paramètre block_action permet de définir le comportement de Nginx lorsqu'une adresse IP présente dans une blocklist est détectée.

Dans nos exemples :

block_action: deny_403

Les requêtes provenant d'une adresse IP présente dans les listes sont alors refusées avec une réponse HTTP 403 Forbidden.

Le paramètre hit_logging_enable permet d'activer la journalisation des blocages.

Avec :

hit_logging_method: dedicated

les blocages sont enregistrés dans un journal dédié, ce qui facilite leur consultation et leur analyse.

drop_444 permet de mettre fin à la connexion.

Consulter l'état des Blocklists

Une fois la configuration enregistrée, rendez-vous dans : INTEGRATIONS → Blocklists IP

Cette page permet de consulter l'état de l'intégration ainsi qu'un récapitulatif des listes configurées et des adresses IP chargées.

Consulter la configuration générée

Vous pouvez également consulter le fichier de configuration généré par NGX Ops depuis : CONFIGURATION → Fichiers de conf → conf.d

Le fichier généré est :

blocklist-ips.conf

Ce fichier contient la configuration nécessaire à la gestion des adresses IP provenant des différentes blocklists.

Configuration des hôtes virtuels pour utiliser Blocklists IP

La configuration des Blocklists IP étant générée au niveau global, il est nécessaire d'indiquer dans chaque hôte virtuel pour lequel vous souhaitez appliquer le filtrage que celui-ci doit utiliser la blocklist.

Pour cela, ajoutez les directives suivantes dans l'hôte virtuel :

# Enregistre les blocages dans un fichier dédié
access_log /var/log/nginx/blocklist-hits.log blocklist_hits if=$blocklist_ip;

# Active le blocage des adresses IP présentes dans les blocklists
include snippets/blocklist-enforce.conf;

La première directive permet d'enregistrer dans un fichier dédié les requêtes provenant d'adresses IP présentes dans les blocklists.

La seconde directive inclut le snippet blocklist-enforce.conf, qui applique effectivement le blocage lorsque la variable $blocklist_ip indique que l'adresse IP du client est présente dans une liste.

Votre hôte virtuel peut donc être configuré de la manière suivante :

server {
    listen 80;
    server_name example.com;

    # Journalise les requêtes bloquées par les blocklists
    access_log /var/log/nginx/blocklist-hits.log blocklist_hits if=$blocklist_ip;

    # Active le blocage des adresses IP présentes dans les blocklists
    include snippets/blocklist-enforce.conf;

    location / {
        proxy_pass http://192.168.1.1;
    }
}

💡 Tip: Le filtrage n'est appliqué qu'aux hôtes virtuels dans lesquels le snippet blocklist-enforce.conf est inclus. Vous pouvez donc choisir précisément les sites et applications auxquels vous souhaitez appliquer les Blocklists IP.

Configurer les liste intégrés analyzer et WAF émulé

Depuis la version 1.1.0 de NGX Ops, il est possible de configurer des bannissements sur les régles de sécurités d'Analyse et sur le WAF Emule pour être exploitrer depuis Blocklists IP.

enable: true
interval_cron: "0 */6 * * *"
block_action: deny_403
hit_logging_enable: true
hit_logging_method: dedicated
sources:
  - name: analyzer-auto
    type: analyzer 
    enable: true
  - name: waf-challenge
    type: waf
    list: challenge
    enable: true
  - name: waf-block
    type: waf
    list: block
    action: drop_444
    enable: true

Configuration avancée des listes

enable: 
interval_cron: "0 */6 * * *"
block_action: drop_444                        # action par défaut des listes
hit_logging_enable: true
hit_logging_method: dedicated
challenge_enable: true                        # obligatoire pour que le challenge s'applique
challenge_engine: builtin
sources:
  - name: datashield
    url: "https://raw.githubusercontent.com/duggytuxy/Data-Shield_IPv4_Blocklist/refs/heads/main/prod_data-shield_ipv4_blocklist.txt"
    enable: true

  - name: paranoid                            # cette liste passe en challenge
    url: "https://intelligence.ngx-ops.net/lists/paranoid.txt"
    action: challenge
    enable: true

Fichier blocklist.yml de référence

Le fichier blocklist.yml centralise la configuration des Blocklists géré par NGX Ops.

# Blocklists IP — sources externes (par URL) et/ou generees localement (par
# l analyseur, voir plus bas), agregees automatiquement, dedupliquees, et
# publiees dans un snippet nginx inclus au niveau http.
#
# Chaque source est recalculee periodiquement (voir interval_cron), fusionnee
# avec les autres et dedupliquee. Une source URL qui echoue temporairement
# (reseau, 404, timeout) ne fait PAS disparaitre ses IP deja connues : la
# derniere liste recue avec succes est mise en cache et reutilisee jusqu au
# prochain succes.
#
# Ne desactivez pas la logique de validation cote code : seules les lignes qui
# ressemblent STRICTEMENT a une adresse IPv4/IPv6 (ou un bloc CIDR) sont
# retenues — toute autre ligne (commentaire, texte, ligne corrompue) est
# ignoree silencieusement plutot que recopiee telle quelle dans la
# configuration nginx generee.

enable: true

# Planification au format cron standard (5 champs, meme moteur que
# config/scheduler.yml) : minute heure jour-du-mois mois jour-de-semaine.
# Exemples : "0 */6 * * *" (toutes les 6h), "0 3 * * *" (tous les jours a 3h),
# "0 */1 * * *" (toutes les heures).
interval_cron: "0 */6 * * *"

# Cadence de la source "analyzer" UNIQUEMENT (v12.53.0). Cette source se calcule
# localement a partir des alertes de l'analyse (aucun telechargement) : la
# rafraichir au rythme de interval_cron (6 h) manquerait les alertes dont la
# fenetre de regle est courte (ex. 5 min) et appliquerait les blocages avec des
# heures de retard. Defaut : chaque minute. Les autres sources (url) ne sont
# retelechargees qu'a interval_cron. nginx n'est recharge que si la liste change.
analyzer_interval_cron: "* * * * *"

# Action appliquee aux IP bloquees par le snippet d'application genere
# (blocklist-enforce.conf) :
#   deny_403 -> renvoie une erreur 403 explicite
#   drop_444 -> ferme la connexion sans reponse (comportement nginx non
#               standard, utile pour ne donner aucune information a un scanner)
block_action: deny_403

# Action PAR LISTE (v12.69.0) : une source `url` peut declarer `action:` pour remplacer
# block_action. Valeurs : deny_403 | drop_444 | challenge. Exemple : drop_444 par defaut,
# mais une liste « moins qualifiee » en challenge (necessite challenge_enable: true) :
#   sources:
#     - name: liste-peu-fiable
#       url: "https://exemple.tld/liste.txt"
#       action: challenge
# Si une IP est dans plusieurs listes, l'action la plus severe l'emporte (444 > 403 > challenge).

# Journalisation dediee des hits (mesure d efficacite, recherche d IP par
# liste, statistiques du Digest) — desactivee par defaut car elle ecrit un
# fichier de log supplementaire. Deux methodes au choix, jamais imposees :
#   dedicated -> log global dedie (blocklist-hits.log), une ligne par requete
#                bloquee, tous vhosts confondus. Precis a 100% (chaque hit
#                logge est bien un blocage blocklist), et ne touche ni ne
#                requiert de desactiver logging.conf ou le format de log
#                partage : c est un `access_log ... if=$blocklist_ip;`
#                independant, ajoute dans blocklist-enforce.conf.
#   approx    -> aucun log dedie. L "efficacite" se limite alors a comparer
#                le nombre d IP bloquees (totalUniqueIps) avec le trafic
#                global — impossible de distinguer un blocage blocklist d un
#                autre blocage sur la meme IP. A reserver aux deploiements
#                qui veulent eviter tout fichier de log supplementaire.
# L agent d analyse (nginx-analyzer) et le controle nginx s adaptent
# automatiquement a la methode choisie ici, sans configuration cote agent.
hit_logging_enable: false
hit_logging_method: dedicated

# ── Remediation "challenge" (v12.63.0) ───────────────────────────────────────
# Une regle d Analyse peut avoir blocklist_remediation_type: challenge : ses IP ne
# sont pas refusees, elles recoivent une page de verification navigateur. Le
# BLOCAGE l emporte : une IP presente dans les deux listes est refusee.
# Mise en place : 1) challenge_enable: true ; 2) demarrer le conteneur
# nginx-challenge (profil compose "challenge") ; 3) ajouter dans chaque vhost
# protege, apres blocklist-enforce.conf :   include snippets/challenge-gate.conf;
# Desactive : les IP "challenge" restent detectees et affichees, mais RIEN n est
# applique dans nginx (ni refus, ni challenge).
challenge_enable: false
# builtin = conteneur nginx-challenge (preuve de travail, cookie signe) ;
# anubis  = Anubis en mode auth_request (voir README)
challenge_engine: builtin
# hote:port du service ; vide = nginx-challenge:8080 (builtin) ou anubis:8923 (anubis)
challenge_upstream: ""
# Resolveur DNS utilise par nginx pour joindre le conteneur (127.0.0.11 = Docker)
challenge_resolver: 127.0.0.11
# Requetes jamais soumises au challenge (regex nginx insensible a la casse ;
# pas d espace, guillemet, antislash, $ ; { } — utiliser [.] pour un point).
# Ex. clients git / API : "^/(api|[^/]+/[^/]+[.]git)/" ; UA : "^(git|curl)/"
challenge_exempt_path_regex: "^/[.]well-known/"
challenge_exempt_ua_regex: ""

sources:
  - name: datashield
    url: "https://raw.githubusercontent.com/duggytuxy/Data-Shield_IPv4_Blocklist/refs/heads/main/prod_data-shield_ipv4_blocklist.txt"
    enable: true

  # Exemple de deuxieme source (desactivee par defaut) — dupliquez ce bloc
  # pour ajouter autant de sources que necessaire, chacune avec un "name"
  # unique (identifiant interne, utilise dans les journaux et le cache).
  # - name: exemple-autre-liste
  #   url: "https://exemple.com/liste-ip.txt"
  #   enable: true

  # Source "analyzer" (mode "a la CrowdSec" fait maison, v12.49.4) — au lieu
  # de recuperer une liste tierce par URL, celle-ci est GENEREE depuis les
  # propres regles d Analyse de nginx-analyzer (bruteforce/scan/flood/
  # scraping/volumetrique/regles personnalisees).
  #
  # v12.50.0 : le seuil de repetition, la fenetre glissante et la decision de
  # bloquer reellement (remediation) ne se configurent PLUS ici — ils vivent
  # desormais AU NIVEAU DE CHAQUE REGLE d Analyse (retour utilisateur : "je
  # vois ça au niveau des regles existantes (1-99) integre et sur les regles
  # perso (100+)"), pour ne jamais melanger un flood tres bruyant et un
  # scraping plus tolerant sous le meme seuil global. Cette source n a donc
  # plus que enable/name : activee, elle agrege le resultat de TOUTES les
  # regles ayant opte, quel que soit leur reglage individuel.
  #
  # Ou configurer une regle : page Analyse -> "Regles d'analyse" pour les
  # regles integrees (bruteforce/scan/flood/scraping/volumetrique/pays), ou
  # directement dans le YAML des regles personnalisees pour les vôtres
  # (id >= 100) : voir nginx-analyzer/lib/rules-yaml.js — champs
  # blocklist_threshold / blocklist_window_minutes / blocklist_remediation /
  # blocklist_remediation_minutes (fenetres exprimees en MINUTES, pas en
  # heures). IMPORTANT : `blocklist_remediation` reste false par defaut, et
  # ce DELIBEREMENT — tant que cette valeur n est pas explicitement passee a
  # true sur une regle, celle-ci alimente la detection (visible, compteur
  # "detecte") mais ne bloque RIEN. Sur un deploiement deja en production,
  # activer cette source pour la premiere fois ne doit jamais bloquer une IP
  # par surprise — on observe d abord ce que la detection produirait.
  #
  # `blocklist_remediation_minutes` (optionnel) fixe une DUREE de blocage :
  # une fois appliquee, l IP reste bloquee ce nombre de minutes (renouvele
  # tant qu elle re-declenche), independamment de la fenetre de comptage.
  # Laisse absent, l IP reste bloquee aussi longtemps qu elle depasse le
  # seuil sur sa fenetre glissante.
  #
  # - name: analyzer-auto
  #   type: analyzer
  #   enable: true

  # Sources "waf" (WAF emule, page « WAF émulé ») : les IP viennent des listes du conteneur
  # ngx-waf, en texte brut, validees ligne a ligne comme n'importe quelle source. Prerequis :
  # config/waf.yml (enable + accept_limits), mode « remediation » sur au moins un vhost
  # (les IP en mode observation ne sont JAMAIS listees). Desactivees ici par defaut.
  #   list: challenge -> IP soumises au challenge navigateur (force action: challenge ;
  #                      exige challenge_enable: true, sinon elles ne sont pas appliquees)
  #   list: block     -> IP refusees avec l'action de la source (defaut : block_action)
  # Si le WAF est injoignable, la derniere liste recue est conservee (comme une source url).
  # Ces sources suivent la cadence analyzer_interval_cron (liste locale, durees courtes).
  # - name: waf-challenge
  #   type: waf
  #   list: challenge
  #   enable: true
  # - name: waf-block
  #   type: waf
  #   list: block
  #   action: drop_444      # optionnel : sinon block_action
  #   enable: true

# Liste blanche (retour utilisateur v12.50.0 : "gerer une liste blanche par
# exemple par d'ip privee donc soit CIDR ou juste une ip") — filet de
# securite GLOBAL, applique apres la fusion de TOUTES les sources (url ou
# analyzer) : une IP ou un bloc CIDR liste ici n est JAMAIS ecrit dans la
# table geo appliquee par nginx, quelle que soit la source qui l aurait
# sinon inclus. Utile en particulier pour vos propres plages privees, afin
# qu un faux positif de la detection "Blocklist a la CrowdSec" ne puisse
# jamais bloquer du trafic interne.
whitelist:
#   - "10.0.0.0/8"
#   - "172.16.0.0/12"
#   - "192.168.0.0/16"
#   - "203.0.113.10"