Aller au contenu

ipset-access: Blocage IP à latence zéro utilisant les ipsets du noyau Linux (v2)

Nécessite le plan Pro (ou supérieur) de l'abonnement GetPageSpeed NGINX Extras.

Installation

Vous pouvez installer ce module dans toute distribution basée sur RHEL, y compris, mais sans s'y limiter :

  • RedHat Enterprise Linux 7, 8, 9 et 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 et Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-ipset-access
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-ipset-access

Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :

load_module modules/ngx_http_ipset_access.so;

Ce document décrit nginx-module-ipset-access v2.0.9 publié le 20 décembre 2025.


Contrôle d'accès basé sur l'IP de niveau entreprise pour NGINX utilisant ipset de Linux. Bloquez les menaces, limitez le taux des abus, défiez les bots et protégez votre infrastructure.

Version GetPageSpeed

⚠️ Logiciel Commercial
Il s'agit d'un module premium à code source fermé disponible exclusivement via le Dépôt GetPageSpeed.

✨ Fonctionnalités

Fonctionnalités principales

Fonctionnalité Description
Liste blanche/Liste noire Autoriser ou refuser en fonction de l'appartenance à l'ipset
Multiples ipsets Vérifiez plusieurs ipsets dans une seule directive
Mises à jour en direct Modifiez les ipsets sans recharger NGINX
Codes d'état personnalisés Retournez n'importe quel statut HTTP lors du blocage

Fonctionnalités de performance

Fonctionnalité Description
Sessions par fil Les sessions libipset locales au fil éliminent la contention de verrouillage
Cache LRU Cache en mémoire partagée avec TTL configurable
Taux de réussite du cache Un taux de réussite typiquement supérieur à 95 % réduit les appels au noyau

Fonctionnalités de sécurité

Fonctionnalité Description
Limitation de taux Limitez les requêtes par IP avec des fenêtres configurables
Auto-interdiction Mettez automatiquement sur liste noire les violateurs de la limite de taux
Défi JS Le défi de preuve de travail arrête les bots automatisés
Pièges honeypot Mettez automatiquement sur liste noire les IPs touchant les URL pièges
Délai d'entrée Expiration automatique des entrées de liste noire

Fonctionnalités opérationnelles

Fonctionnalité Description
Mode dry-run Testez la configuration sans bloquer
Fail-open/close Contrôlez le comportement en cas d'erreurs d'ipset
Métriques Prometheus Point de terminaison /metrics natif pour Grafana
Statistiques JSON API de statistiques détaillées
Variables NGINX $ipset_result et $ipset_matched_set

🚀 Démarrage rapide

1. Créer des ipsets

## Créer une liste noire
sudo ipset create bad_guys hash:ip timeout 86400

## Créer une liste d'interdiction de limitation de taux  
sudo ipset create ratelimited hash:ip timeout 1800

## Créer une liste de pièges honeypot
sudo ipset create honeypot hash:ip timeout 86400

2. Configurer NGINX

load_module modules/ngx_http_ipset_access_module.so;

http {
    server {
        listen 80;

        # Bloquer les IPs connues comme mauvaises
        ipset_blacklist bad_guys;

        # Limitation de taux : 100 requêtes par minute
        ipset_ratelimit rate=100 window=60s autoban=ratelimited;

        # Votre contenu
        location / {
            root /var/www/html;
        }

        # Piège honeypot - retourne 404 par défaut
        location /wp-admin.php {
            ipset_autoadd honeypot timeout=86400;
        }

        # Point de terminaison des métriques
        location /metrics {
            ipset_metrics;
            allow 127.0.0.1;
            deny all;
        }
    }
}

3. Tester et recharger

sudo nginx -t && sudo nginx -s reload

📦 Installation

Ce module est disponible exclusivement via le Dépôt Premium GetPageSpeed.

Étape 1 : S'abonner au Dépôt GetPageSpeed

Visitez Abonnement au Dépôt GetPageSpeed pour obtenir l'accès.

Étape 2 : Installer le Dépôt

## RHEL/CentOS/Rocky/Alma Linux 8+
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm

Étape 3 : Installer le Module

sudo dnf install nginx-module-ipset-access

Étape 4 : Activer le Module

Ajoutez à /etc/nginx/nginx.conf avant tout bloc http {} :

load_module modules/ngx_http_ipset_access_module.so;

Étape 5 : Recharger NGINX

sudo nginx -t && sudo systemctl reload nginx

📖 Référence de configuration

Contrôle d'accès

ipset_blacklist set1 [set2 ...]

Contexte : http, server
Par défaut :

Bloque les requêtes si l'IP client apparaît dans n'importe lequel des ipsets listés. Plusieurs ipsets sont vérifiés dans l'ordre jusqu'à ce qu'une correspondance soit trouvée.

## Ensemble unique
ipset_blacklist bad_guys;

## Ensembles multiples (logique OU - bloqué si dans UN SEUL ensemble)
ipset_blacklist spammers hackers tor_exits;

## Désactiver
ipset_blacklist off;

ipset_whitelist set1 [set2 ...]

Contexte : http, server
Par défaut :

Autorise les requêtes uniquement si l'IP client apparaît dans au moins un des ipsets listés. Toutes les autres IPs sont rejetées.

## Autoriser uniquement les IPs de confiance
ipset_whitelist trusted_partners office_ips;

Important : Les IPs sur liste blanche contournent toutes les restrictions du module, y compris : - Limitation de taux (ipset_ratelimit) - Défis JavaScript (ipset_challenge)

Ceci est utile pour les IPs administratives qui ne devraient pas être soumises à des limites de taux ou à des défis :

## Les IPs administratives contournent la limitation de taux et les défis
ipset_whitelist admin_ips;
ipset_ratelimit rate=100 window=1m autoban=ratelimited ban_time=1800;
ipset_challenge on;

ipset_status code

Contexte : http, server
Par défaut : 403

Code d'état HTTP retourné lorsqu'une requête est bloquée.

ipset_status 403;   # Interdit (par défaut)
ipset_status 444;   # Fermer la connexion sans réponse (spécial NGINX)
ipset_status 429;   # Trop de requêtes
ipset_status 503;   # Service indisponible

Mise en cache & Performance

ipset_cache_ttl time

Contexte : http, server
Par défaut : 60s

Combien de temps mettre en cache les résultats de recherche d'ipset. Les résultats mis en cache évitent les appels répétés au noyau pour la même IP.

ipset_cache_ttl 30s;    # 30 secondes
ipset_cache_ttl 5m;     # 5 minutes
ipset_cache_ttl 1h;     # 1 heure

Note de débogage : Si vous retirez une IP d'un ipset mais que le module continue de la signaler comme "correspondante", cela est dû à la mise en cache. Le résultat mis en cache expirera après le TTL configuré. Pour un effet immédiat lors des tests, vous pouvez temporairement définir ipset_cache_ttl 0; pour désactiver la mise en cache (non recommandé pour la production en raison de l'impact sur les performances).

Impact sur les performances : - TTL plus élevé = Meilleures performances, mais plus lent à refléter les changements d'ipset - TTL plus bas = Plus réactif aux changements d'ipset, mais plus d'appels au noyau - Recommandé : 30s à 5m pour la plupart des cas d'utilisation

ipset_fail_open on|off

Contexte : http, server
Par défaut : off

Contrôle le comportement lorsqu'une recherche d'ipset échoue (par exemple, l'ensemble n'existe pas).

ipset_fail_open off;   # Refuser en cas d'erreur (sécurisé, par défaut)
ipset_fail_open on;    # Autoriser en cas d'erreur (disponible mais risqué)

ipset_dryrun on|off

Contexte : http, server
Par défaut : off

Lorsqu'il est activé, journalise ce qui serait bloqué mais ne bloque pas réellement. Parfait pour tester de nouvelles règles en production.

ipset_dryrun on;   # Journaliser mais ne pas bloquer

Vérifiez les journaux pour des messages comme :

ipset: DRYRUN would block 1.2.3.4 (matched: bad_guys)

Important : Lorsque vous utilisez les variables $ipset_result et $ipset_matched_set avec le mode dryrun, ces valeurs reflètent l'état à un moment donné lorsque la requête a été traitée - pas l'état actuel de l'ipset. Si vous vérifiez l'ipset manuellement plus tard et ne trouvez pas l'IP, les raisons possibles incluent :

  1. Expiration du délai : L'IP a été ajoutée avec un délai (par exemple, timeout=86400) et a depuis expiré
  2. Retard de cache : Le module met en cache les résultats de recherche (par défaut 60s). Une entrée retirée de l'ipset peut encore apparaître comme "correspondante" jusqu'à ce que le cache expire
  3. Retrait manuel : Quelqu'un ou quelque chose (fail2ban, scripts) a retiré l'entrée

C'est un comportement attendu - le dryrun vous montre exactement ce que la production verrait au moment de la requête.

Limitation de taux

ipset_ratelimit parameters

Contexte : http, server
Par défaut :

Limite les requêtes par IP dans une fenêtre temporelle. Peut ajouter automatiquement les violateurs à un ipset.

Paramètres :

Paramètre Requis Description
rate=N Oui Maximum de requêtes par fenêtre
window=TIME Non Fenêtre temporelle (par défaut : 60s)
autoban=SET Non ipset pour ajouter les violateurs
ban_time=N Non Secondes jusqu'à expiration automatique (par défaut : 3600)

Exemples :

## Basique : 100 requêtes par minute
ipset_ratelimit rate=100;

## Avec fenêtre personnalisée : 1000 requêtes par heure
ipset_ratelimit rate=1000 window=1h;

## Avec auto-interdiction : Ajouter les violateurs à l'ipset pendant 30 minutes
ipset_ratelimit rate=60 window=1m autoban=ratelimited ban_time=1800;

## Protection API stricte
ipset_ratelimit rate=10 window=1s autoban=api_abusers ban_time=3600;

Comment ça fonctionne : 1. Chaque IP obtient un compteur de requêtes et un temps de début de fenêtre 2. Le compteur s'incrémente à chaque requête 3. Lorsque la fenêtre expire, le compteur se réinitialise 4. Si le compteur dépasse rate, retourne 429 Trop de requêtes 5. Si autoban est défini, l'IP est ajoutée à l'ipset spécifié

Remarque : L'état de limitation de taux est stocké en mémoire partagée et survit aux redémarrages des travailleurs.

Défi JavaScript

ipset_challenge on|off

Contexte : http, server
Par défaut : off

Active le mode défi JavaScript. Les navigateurs doivent résoudre une énigme de preuve de travail pour accéder au site. Efficace contre les bots automatisés et les scrapers.

ipset_challenge on;

Comment ça fonctionne : 1. La première requête reçoit une page de défi (HTTP 503) 2. Le navigateur exécute JavaScript qui résout une énigme de hachage 3. La solution est stockée dans un cookie (_ipset_verified) 4. Les requêtes suivantes avec un cookie valide passent 5. Le cookie expire après 24 heures

ipset_challenge_difficulty level

Contexte : http, server
Par défaut : 2

Contrôle la difficulté du défi (1-8). Plus élevé = temps de résolution plus long.

Niveau Temps de résolution approximatif
1 ~100ms
2 ~500ms (par défaut)
3 ~1 seconde
4 ~2 secondes
5 ~5 secondes
6+ ~10+ secondes
ipset_challenge on;
ipset_challenge_difficulty 3;  # ~1 seconde de temps de résolution

Fonctionnalités de la page de défi : - Design moderne et réactif - Indicateur de chargement animé - Retour d'information sur la progression - Redirection automatique en cas de succès - Pas de dépendances externes

Auto-ajout Honeypot

ipset_autoadd setname [timeout=seconds] [status=code]

Contexte : server, location
Par défaut :

Ajoute automatiquement l'IP client à l'ipset spécifié lorsque la localisation est accédée et retourne un code d'état HTTP. Parfait pour les pièges honeypot.

Paramètres :

Paramètre Requis Description
setname Oui Nom de l'ipset cible
timeout=N Non Délai d'entrée en secondes
status=N Non Code d'état HTTP à retourner (par défaut : 404)

Exemples :

## Basique : Ajouter au jeu honeypot et retourner 404 (par défaut)
location /config.php {
    ipset_autoadd honeypot;
}

## Avec délai : Expiration automatique après 24 heures
location /wp-admin.php {
    ipset_autoadd scanners timeout=86400;
}

## Retourner 403 Interdit au lieu de 404
location /admin.php {
    ipset_autoadd honeypot timeout=86400 status=403;
}

## Retourner 429 Trop de requêtes
location /api/hack {
    ipset_autoadd abusers timeout=3600 status=429;
}

Chemins de piège Honeypot courants :

## Pièges WordPress - retourner 404 pour ressembler à un fichier manquant
location ~ ^/(wp-admin\.php|wp-login\.php|xmlrpc\.php)$ {
    ipset_autoadd honeypot timeout=86400;
}

## Pièges de fichiers de configuration - retourner 403 pour simuler un accès interdit
location ~ ^/(\\.env|config\\.php|phpinfo\\.php)$ {
    ipset_autoadd honeypot timeout=86400 status=403;
}

## Pièges de shell/exploit - sévère, bloquer pendant 1 semaine
location ~ ^/(shell|cmd|eval|exec)\\.php$ {
    ipset_autoadd malicious timeout=604800 status=403;
}

Remarque : Lorsqu'une IP est auto-ajoutée, le module retourne immédiatement le code d'état HTTP spécifié (404 par défaut), empêchant tout traitement ultérieur de la requête. Le keep-alive de la connexion est également désactivé pour éviter d'autres requêtes sur la même connexion.

Observabilité

ipset_stats

Contexte : location
Par défaut :

Active le point de terminaison de statistiques JSON.

location = /_stats {
    ipset_stats;
    allow 127.0.0.1;
    allow 10.0.0.0/8;
    deny all;
}

Voir API de statistiques JSON pour le format de réponse.

ipset_metrics

Contexte : location
Par défaut :

Active le point de terminaison des métriques Prometheus.

location = /metrics {
    ipset_metrics;
    allow 127.0.0.1;
    allow 10.0.0.0/8;
    deny all;
}

Voir Métriques Prometheus pour les métriques disponibles.

📝 Variables NGINX

Le module expose deux variables à utiliser dans les journaux, les en-têtes ou les conditionnels.

$ipset_result

La décision d'accès prise pour cette requête.

Valeur Description
allow Requête autorisée
deny Requête bloquée
dryrun Serait bloqué (mode dry-run)
ratelimited Limite de taux dépassée
challenged Page de défi servie

$ipset_matched_set

Nom de l'ipset qui a correspondu (le cas échéant). Vide s'il n'y a pas de correspondance.

Remarque : Cette variable reflète l'état de correspondance au moment de la requête, pas l'état actuel de l'ipset. Si vous vérifiez l'ipset manuellement et ne trouvez pas l'IP : - L'entrée peut avoir expiré (les ipsets prennent en charge les délais par entrée) - Le cache du module (par défaut 60s) peut montrer une entrée récemment retirée comme encore correspondante - Quelque chose a pu retirer l'entrée après que la requête ait été traitée

Exemples d'utilisation

Journal d'accès personnalisé :

log_format security '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    'ipset_result="$ipset_result" '
                    'matched_set="$ipset_matched_set"';

access_log /var/log/nginx/security.log security;

Ajouter des en-têtes pour le débogage :

add_header X-IPSet-Result $ipset_result always;
add_header X-IPSet-Matched $ipset_matched_set always;

Journalisation conditionnelle :

## Ne journaliser que les requêtes bloquées
map $ipset_result $loggable {
    "deny"  1;
    default 0;
}

access_log /var/log/nginx/blocked.log combined if=$loggable;

📊 Métriques Prometheus

Le point de terminaison /metrics retourne des métriques au format d'exposition Prometheus.

Métriques disponibles

## HELP nginx_ipset_requests_total Total des requêtes traitées
## TYPE nginx_ipset_requests_total counter
nginx_ipset_requests_total{result="checked"} 1234567
nginx_ipset_requests_total{result="allowed"} 1234000
nginx_ipset_requests_total{result="blocked"} 500
nginx_ipset_requests_total{result="error"} 67

## HELP nginx_ipset_cache_total Opérations de cache
## TYPE nginx_ipset_cache_total counter
nginx_ipset_cache_total{result="hit"} 1200000
nginx_ipset_cache_total{result="miss"} 34567

## HELP nginx_ipset_cache_entries Entrées de cache actuelles
## TYPE nginx_ipset_cache_entries gauge
nginx_ipset_cache_entries 5432

## HELP nginx_ipset_autoadd_total Opérations d'auto-ajout
## TYPE nginx_ipset_autoadd_total counter
nginx_ipset_autoadd_total{result="success"} 42
nginx_ipset_autoadd_total{result="failed"} 3

## HELP nginx_ipset_ratelimit_total Événements de limitation de taux
## TYPE nginx_ipset_ratelimit_total counter
nginx_ipset_ratelimit_total{action="triggered"} 156
nginx_ipset_ratelimit_total{action="autobanned"} 23

## HELP nginx_ipset_challenge_total Événements de défi
## TYPE nginx_ipset_challenge_total counter
nginx_ipset_challenge_total{result="issued"} 1000
nginx_ipset_challenge_total{result="passed"} 950
nginx_ipset_challenge_total{result="failed"} 50

## HELP nginx_ipset_uptime_seconds Temps de fonctionnement du module
## TYPE nginx_ipset_uptime_seconds gauge
nginx_ipset_uptime_seconds 86400

Requêtes de tableau de bord Grafana

Taux de requêtes par résultat :

rate(nginx_ipset_requests_total[5m])

Taux de blocage :

rate(nginx_ipset_requests_total{result="blocked"}[5m])

Taux de réussite du cache :

rate(nginx_ipset_cache_total{result="hit"}[5m]) / 
(rate(nginx_ipset_cache_total{result="hit"}[5m]) + rate(nginx_ipset_cache_total{result="miss"}[5m]))

Déclencheurs de limitation de taux par minute :

rate(nginx_ipset_ratelimit_total{action="triggered"}[1m]) * 60

📈 API de statistiques JSON

Le point de terminaison /_stats retourne des statistiques détaillées au format JSON.

Format de réponse

{
  "version": "2.0.7",
  "uptime_seconds": 86400,
  "requests": {
    "checked": 1234567,
    "allowed": 1234000,
    "blocked": 500,
    "errors": 67
  },
  "cache": {
    "hits": 1200000,
    "misses": 34567,
    "entries": 5432,
    "hit_rate": 97.20
  },
  "autoadd": {
    "success": 42,
    "failed": 3
  },
  "ratelimit": {
    "triggered": 156,
    "autobanned": 23
  },
  "challenge": {
    "issued": 1000,
    "passed": 950,
    "failed": 50
  }
}

Descriptions des champs

Champ Description
version Version du module
uptime_seconds Secondes depuis le chargement du module
requests.checked Total des requêtes traitées
requests.allowed Requêtes qui ont passé
requests.blocked Requêtes qui ont été bloquées
requests.errors Erreurs de recherche d'ipset
cache.hits Succès de cache (évité appel au noyau)
cache.misses Échecs de cache (appel au noyau requis)
cache.entries Entrées mises en cache actuelles
cache.hit_rate Pourcentage de taux de réussite
autoadd.success Ajouts réussis de honeypot
autoadd.failed Échecs d'ajout de honeypot
ratelimit.triggered Violations de limitation de taux
ratelimit.autobanned IPs ajoutées automatiquement à la liste d'interdiction
challenge.issued Pages de défi servies
challenge.passed Défis résolus avec succès
challenge.failed Échecs de défi

🏗️ Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                           FLUX DE REQUÊTE                             │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│   Requête entrante                                                  │
│         │                                                            │
│         ▼                                                            │
│   ┌───────────────┐                                                  │
│   │  Vérification  │──── Dépassé ? ────▶ 429 + Auto-interdiction     │
│   │    de taux     │                                                  │
│   └───────┬───────┘                                                  │
│           │ OK                                                       │
│           ▼                                                          │
│   ┌───────────────┐                                                  │
│   │   Vérification │──── Pas de cookie ? ────▶ Servir JS Puzzle     │
│   │    de défi     │                                                  │
│   └───────┬───────┘                                                  │
│           │ Réussi                                                   │
│           ▼                                                          │
│   ┌───────────────┐     ┌─────────────┐                             │
│   │  Vérification  │────▶│   HIT       │────▶ Utiliser le résultat mis en cache  │
│   └───────┬───────┘     └─────────────┘                             │
│           │ MANQUE                                                 │
│           ▼                                                          │
│   ┌───────────────┐                                                  │
│   │  Requête ipset │──── Session libipset locale au fil              │
│   │  (noyau)      │                                                  │
│   └───────┬───────┘                                                  │
│           │                                                          │
│           ▼                                                          │
│   ┌───────────────┐                                                  │
│   │ Stocker dans le cache│                                              │
│   └───────┬───────┘                                                  │
│           │                                                          │
│           ▼                                                          │
│   ┌───────────────┐                                                  │
│   │    Décision    │──── Correspondance sur liste noire ? ────▶ Bloquer (403/444)  │
│   │                │──── Correspondance sur liste blanche ? ────▶ Bloquer (403/444)  │
│   └───────┬───────┘                                                  │
│           │ Autoriser                                                │
│           ▼                                                          │
│   ┌───────────────┐                                                  │
│   │   Vérification  │──── Correspondance de localisation ? ────▶ Ajouter à l'ipset  │
│   │    honeypot    │                                                  │
│   └───────┬───────┘                                                  │
│           │                                                          │
│           ▼                                                          │
│       Continuer vers                                               │
│       le gestionnaire de contenu                                     │
│                                                                      │
├─────────────────────────────────────────────────────────────────────┤
│                        MÉMOIRE PARTAGÉE                              │
│  ┌────────────────┬─────────────────┬─────────────────────────────┐ │
│  │     Statistiques │    Cache LRU    │    Seaux de limitation de taux │ │
│  │   (compteurs)   │  (IP → Résultat)  │   (IP → Compteur de requêtes)  │ │
│  └────────────────┴─────────────────┴─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘

Disposition de la mémoire

Composant Emplacement Objectif
Session libipset Locale au fil Session par travailleur pour éviter les verrous
Cache de recherche Mémoire partagée Cache LRU des mappages IP→résultat
Seaux de limitation de taux Mémoire partagée Compteurs de requêtes par IP
Statistiques Mémoire partagée Compteurs atomiques pour les métriques

📚 Exemples

Exemple 1 : Liste noire basique

## Créer un ipset
sudo ipset create blacklist hash:ip
sudo ipset add blacklist 1.2.3.4
    server {
    listen 80;

    ipset_blacklist blacklist;

    location / {
        root /var/www/html;
    }
}

Exemple 2 : API avec limitation de taux

server {
    listen 80;

    # Limitation stricte de taux pour l'API
    ipset_ratelimit rate=100 window=1m autoban=api_banned ban_time=3600;

    # Autoriser uniquement les partenaires connus
    ipset_whitelist api_partners;
    ipset_status 401;

    location /api/ {
        proxy_pass http://backend;
    }
}

Exemple 3 : Pile de sécurité complète

    server {
        listen 80 default_server;

    # Couche 1 : Menaces connues
    ipset_blacklist malware_ips tor_exits datacenter_ranges;
    ipset_status 444;
    ipset_cache_ttl 5m;

    # Couche 2 : Limitation de taux
    ipset_ratelimit rate=60 window=1m autoban=ratelimited ban_time=1800;

    # Couche 3 : Défi de bot
    ipset_challenge on;
    ipset_challenge_difficulty 2;

    # Contenu réel
        location / {
        root /var/www/html;
    }

    # Pièges honeypot - retourner 404 (par défaut) pour ressembler à des fichiers manquants
    location ~ ^/(wp-admin|phpmyadmin|admin)\.php$ {
        ipset_autoadd honeypot timeout=86400;
    }

    # Surveillance
    location = /metrics {
        ipset_metrics;
        allow 10.0.0.0/8;
        deny all;
    }
}

Exemple 4 : Test en mode dry-run

server {
    listen 80;

    # Tester de nouvelles règles sans bloquer
    ipset_blacklist new_threat_list;
    ipset_dryrun on;

    location / {
        root /var/www/html;
    }
}

Vérifiez les journaux :

tail -f /var/log/nginx/error.log | grep "DRYRUN"

🔧 Dépannage

Module ne se charge pas

nginx: [emerg] dlopen() failed

Solution : Assurez-vous que NGINX a été construit avec --with-compat et que le module a été construit contre la même version de NGINX.

ipset non trouvé

ipset: INVALID_SETNAME

Solution : Créez l'ipset avant de démarrer NGINX :

sudo ipset create myset hash:ip

Permission refusée

ipset: kernel error

Solution : Le travailleur NGINX a besoin de la capacité CAP_NET_ADMIN :

sudo setcap cap_net_admin+ep /usr/sbin/nginx

Refus SELinux (RHEL/CentOS/AlmaLinux)

SELinux empêche /usr/sbin/nginx d'accéder à getattr sur le netlink_netfilter_socket

Solution : Installez le module de politique SELinux inclus :

cd selinux/
sudo ./install.sh

Ou manuellement :

## Vérifier
semodule -l | grep nginx_ipset

La politique permet à httpd_t (le domaine SELinux de NGINX) d'utiliser les sockets netlink_netfilter requis par libipset.

Utilisation élevée de la mémoire

Solution : Réduisez le TTL du cache ou limitez la taille du cache dans la configuration de la mémoire partagée.

Limitation de taux non fonctionnelle

Solution : Assurez-vous que l'ipset pour l'auto-interdiction existe et prend en charge les délais :

sudo ipset create ratelimited hash:ip timeout 3600

Le journal montre "matched=setname" mais l'IP n'est pas dans l'ipset

C'est un comportement attendu. Le module signale ce qu'il a vu au moment de la requête. Si vous vérifiez l'ipset plus tard et ne trouvez pas l'IP :

  1. Expiration du délai : L'IP a été ajoutée avec un délai et a depuis expiré

    # Vérifiez si l'ensemble prend en charge les délais
    ipset list setname | head -5
    # Recherchez "timeout" dans l'en-tête
    

  2. Cache du module : Le module met en cache les recherches (par défaut 60s). Une IP récemment retirée peut encore apparaître comme "correspondante"

    # Désactiver temporairement le cache pour le débogage (pas pour la production !)
    ipset_cache_ttl 0;
    

  3. L'entrée a été retirée : fail2ban, des scripts ou des commandes manuelles peuvent l'avoir retirée

  4. Problème de configuration de piège : Si vous utilisez des pièges honeypot avec ipset_autoadd, des bots légitimes peuvent avoir déclenché des pièges. Vérifiez que vos emplacements de piège ne se chevauchent pas avec des chemins de bots légitimes (comme les sitemaps, robots.txt). Utilisez robots.txt pour exclure les chemins de piège du crawling.

autoadd échoue avec "result=4"

Cela signifie que vous utilisez timeout=N dans ipset_autoadd mais que l'ipset a été créé sans prise en charge des délais.

Solution : Recréez l'ipset avec prise en charge des délais :

## En utilisant ipset directement
sudo ipset destroy honeypot4
sudo ipset create honeypot4 hash:ip family inet timeout 86400

## En utilisant firewall-cmd (RHEL/CentOS/Amazon Linux)
sudo firewall-cmd --permanent --delete-ipset=honeypot4
sudo firewall-cmd --permanent --new-ipset=honeypot4 --type=hash:ip \
    --option=family=inet --option=timeout=86400
sudo firewall-cmd --reload

📋 Exigences

  • NGINX ≥ 1.22 (construit avec --with-compat)
  • Noyau Linux avec prise en charge d'ipset (module nf_tables ou xt_set)
  • Bibliothèque libipset et en-têtes de développement
  • Capacités : CAP_NET_ADMIN pour les opérations d'ipset

📜 Licence

Il s'agit d'un logiciel propriétaire. Tous droits réservés.

Disponible exclusivement via le Dépôt Premium GetPageSpeed.

👤 Auteur

Danila Vershinin
GetPageSpeed LLC

🆘 Support

Module d'accès NGINX IPSet
Un module NGINX premium de GetPageSpeed LLC
www.getpagespeed.com