nftset-access: Blocage IP à latence nulle utilisant les ensembles nftables du noyau Linux
Nécessite le plan Pro (ou supérieur) de l'abonnement GetPageSpeed NGINX Extras.
Installation
Vous pouvez installer ce module dans n'importe quelle 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-nftset-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-nftset-access
Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :
load_module modules/ngx_http_nftset_access.so;
Ce document décrit nginx-module-nftset-access v3.0.0 publié le 14 février 2026.
Contrôle d'accès basé sur l'IP de niveau entreprise pour NGINX utilisant les ensembles nftables de Linux. Bloquez les menaces, limitez le taux des abus, défiez les bots et protégez votre infrastructure.
⚠️ Logiciel Commercial Il s'agit d'un module premium à code source fermé disponible exclusivement via le GetPageSpeed Repository.
Exigence de plan : Nécessite le plan Pro de l'abonnement GetPageSpeed NGINX Extras.
✨ Fonctionnalités
Fonctionnalités principales
| Fonctionnalité | Description |
|---|---|
| Liste blanche/Liste noire | Autoriser ou interdire en fonction de l'appartenance à l'ensemble nftables |
| Ensembles multiples | Vérifiez plusieurs ensembles nft dans une seule directive |
| Mises à jour en direct | Modifiez les ensembles nft sans recharger NGINX |
| Codes d'état personnalisés | Retournez tout code HTTP lors du blocage |
| Support CIDR | Utilisez des ensembles d'intervalles pour les plages réseau (par exemple, 192.168.1.0/24) |
Fonctionnalités de performance
| Fonctionnalité | Description |
|---|---|
| Sessions par thread | Contextes libnftables locaux au thread éliminent la contention de verrouillage |
| Cache LRU | Cache en mémoire partagée avec TTL configurable |
| Taux de réussite du cache | 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 | Liste noire automatique des IP 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'ensemble nft |
| Métriques Prometheus | Point de terminaison /metrics natif pour Grafana |
| Statistiques JSON | API de statistiques détaillées |
| Variables NGINX | $nftset_result et $nftset_matched_set |
🚀 Démarrage rapide
1. Créer des ensembles nftables
# Créer une table (si elle n'existe pas)
sudo nft add table ip filter
# Créer une liste noire avec support de délai d'expiration
sudo nft add set ip filter bad_guys '{ type ipv4_addr; flags timeout; timeout 1d; }'
# Créer une liste de bannissement par limite de taux
sudo nft add set ip filter ratelimited '{ type ipv4_addr; flags timeout; timeout 30m; }'
# Créer une liste de pièges honeypot
sudo nft add set ip filter honeypot '{ type ipv4_addr; flags timeout; timeout 1d; }'
# Créer une liste blanche avec support CIDR
sudo nft add set ip filter trusted '{ type ipv4_addr; flags interval; }'
sudo nft add element ip filter trusted '{ 10.0.0.0/8, 192.168.0.0/16 }'
2. Configurer NGINX
load_module modules/ngx_http_nftset_access_module.so;
http {
server {
listen 80;
# Bloquer les IPs connues comme mauvaises (format : table:setname)
nftset_blacklist filter:bad_guys;
# Limitation de taux : 100 requêtes par minute
nftset_ratelimit rate=100 window=60s autoban=filter:ratelimited;
# Votre contenu
location / {
root /var/www/html;
}
# Piège honeypot - retourne 404 par défaut
location /wp-admin.php {
nftset_autoadd filter:honeypot timeout=86400;
}
# Point de terminaison des métriques
location /metrics {
nftset_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 GetPageSpeed Premium Repository.
Étape 1 : S'abonner au GetPageSpeed Repository
Visitez GetPageSpeed Repository Subscription pour obtenir l'accès.
Étape 2 : Installer le Repository
# 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-nftset-access
Étape 4 : Activer le Module
Ajoutez à /etc/nginx/nginx.conf avant tout bloc http {} :
load_module modules/ngx_http_nftset_access_module.so;
Étape 5 : Recharger NGINX
sudo nginx -t && sudo systemctl reload nginx
📖 Référence de configuration
Format de spécification d'ensemble
Toutes les directives qui font référence aux ensembles nftables utilisent le format : table:setname
table— Le nom de la table nftables (par exemple,filter,firewalld)setname— Le nom de l'ensemble dans cette table
La famille IP (ip pour IPv4, ip6 pour IPv6) est auto-détectée à partir de l'adresse IP du client.
Exemples :
nftset_blacklist filter:blocklist; # Client IPv4 → ip filter blocklist
# Client IPv6 → ip6 filter blocklist
nftset_whitelist filter:trusted;
nftset_autoadd filter:honeypot timeout=3600;
Contrôle d'accès
nftset_blacklist table:set1 [table:set2 ...]
Contexte : http, server
Par défaut : —
Bloque les requêtes si l'IP du client apparaît dans n'importe lequel des ensembles nft listés. Plusieurs ensembles sont vérifiés dans l'ordre jusqu'à ce qu'une correspondance soit trouvée.
# Ensemble unique
nftset_blacklist filter:bad_guys;
# Ensembles multiples (logique OU - bloqué si dans UN ensemble)
nftset_blacklist filter:spammers filter:hackers filter:tor_exits;
# Désactiver
nftset_blacklist off;
nftset_whitelist table:set1 [table:set2 ...]
Contexte : http, server
Par défaut : —
Autorise les requêtes uniquement si l'IP du client apparaît dans au moins un des ensembles nft listés. Toutes les autres IP sont rejetées.
# Autoriser uniquement les IPs de confiance
nftset_whitelist filter:trusted_partners filter:office_ips;
Important : Les IPs sur liste blanche contournent toutes les restrictions du module, y compris :
- Limitation de taux (nftset_ratelimit)
- Défis JavaScript (nftset_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 les limitations de taux et les défis
nftset_whitelist filter:admin_ips;
nftset_ratelimit rate=100 window=1m autoban=filter:ratelimited ban_time=1800;
nftset_challenge on;
nftset_status code
Contexte : http, server
Par défaut : 403
Code d'état HTTP retourné lorsqu'une requête est bloquée.
nftset_status 403; # Interdit (par défaut)
nftset_status 444; # Fermer la connexion sans réponse (spécial NGINX)
nftset_status 429; # Trop de requêtes
nftset_status 503; # Service indisponible
Mise en cache & Performance
nftset_cache_ttl time
Contexte : http, server
Par défaut : 60s
Combien de temps mettre en cache les résultats de recherche d'ensemble nft. Les résultats mis en cache évitent les appels répétés au noyau pour la même IP.
nftset_cache_ttl 30s; # 30 secondes
nftset_cache_ttl 5m; # 5 minutes
nftset_cache_ttl 1h; # 1 heure
Remarque de débogage : Si vous retirez une IP d'un ensemble nft 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 nftset_cache_ttl 0; pour désactiver la mise en cache (non recommandé pour la production en raison de l'impact sur la performance).
Impact sur la performance :
- TTL plus élevé = Meilleure performance, mais plus lent à refléter les changements d'ensemble nft
- TTL plus bas = Plus réactif aux changements d'ensemble nft, mais plus d'appels au noyau
- Recommandé : 30s à 5m pour la plupart des cas d'utilisation
nftset_fail_open on|off
Contexte : http, server
Par défaut : off
Contrôle le comportement lorsqu'une recherche d'ensemble nft échoue (par exemple, l'ensemble n'existe pas).
nftset_fail_open off; # Refuser en cas d'erreur (sécurisé, par défaut)
nftset_fail_open on; # Autoriser en cas d'erreur (disponible mais risqué)
nftset_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.
nftset_dryrun on; # Journaliser mais ne pas bloquer
Vérifiez les journaux pour des messages comme :
nftset: DRYRUN would block 1.2.3.4 (matched: filter:bad_guys)
Important : Lorsque vous utilisez les variables $nftset_result et $nftset_matched_set avec le mode dryrun, ces valeurs reflètent l'état à un instant donné lorsque la requête a été traitée - pas l'état actuel de l'ensemble nft. Si vous vérifiez l'ensemble nft manuellement plus tard et ne trouvez pas l'IP, les raisons possibles incluent :
- Expiration du délai : L'IP a été ajoutée avec un délai (par exemple,
timeout 1d) et a depuis expiré - Retard de cache : Le module met en cache les résultats de recherche (par défaut 60s). Une entrée retirée de l'ensemble nft peut encore apparaître comme "correspondante" jusqu'à ce que le cache expire
- 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
nftset_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 ensemble nft.
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=TABLE:SET |
Non | ensemble nft à ajouter aux violateurs |
ban_time=N |
Non | Secondes jusqu'à expiration automatique (par défaut : 3600) |
Exemples :
# Basique : 100 requêtes par minute
nftset_ratelimit rate=100;
# Avec fenêtre personnalisée : 1000 requêtes par heure
nftset_ratelimit rate=1000 window=1h;
# Avec auto-interdiction : Ajouter les violateurs à l'ensemble nft pendant 30 minutes
nftset_ratelimit rate=60 window=1m autoban=filter:ratelimited ban_time=1800;
# Protection API stricte
nftset_ratelimit rate=10 window=1s autoban=filter: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'ensemble nft spécifié
Remarque : L'état de la limite de taux est stocké en mémoire partagée et survit aux redémarrages des travailleurs.
Défi JavaScript
nftset_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.
nftset_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 (_nftset_verified)
4. Les requêtes suivantes avec un cookie valide passent
5. Le cookie expire après 24 heures
nftset_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 |
nftset_challenge on;
nftset_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
nftset_autoadd table:setname [table:setname2 ...] [timeout=seconds] [status=code]
Contexte : server, location
Par défaut : —
Ajoute automatiquement l'IP du client aux ensembles nft spécifiés 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 |
|---|---|---|
| table:setname | Oui | Ensemble nft cible (peut spécifier plusieurs) |
timeout=N |
Non | Délai d'expiration de l'entrée en secondes |
status=N |
Non | Code d'état HTTP à retourner (par défaut : 404) |
Exemples :
# Basique : Ajouter à l'ensemble honeypot et retourner 404 (par défaut)
location /config.php {
nftset_autoadd filter:honeypot;
}
# Avec délai : Expiration automatique après 24 heures
location /wp-admin.php {
nftset_autoadd filter:scanners timeout=86400;
}
# Retourner 403 Interdit au lieu de 404
location /admin.php {
nftset_autoadd filter:honeypot timeout=86400 status=403;
}
# Ajouter à plusieurs ensembles (IPv4 et IPv6)
location /trap {
nftset_autoadd filter:honeypot4 filter:honeypot6 timeout=86400;
}
Chemins de piège courants :
# Pièges WordPress - retourne 404 pour sembler être un fichier manquant
location ~ ^/(wp-admin\.php|wp-login\.php|xmlrpc\.php)$ {
nftset_autoadd filter:honeypot timeout=86400;
}
# Pièges de fichiers de configuration - retourne 403 pour simuler un accès interdit
location ~ ^/(\.env|config\.php|phpinfo\.php)$ {
nftset_autoadd filter:honeypot timeout=86400 status=403;
}
# Pièges de shell/exploit - sévère, bloquer pendant 1 semaine
location ~ ^/(shell|cmd|eval|exec)\.php$ {
nftset_autoadd filter: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 de requête ultérieur. Le keep-alive de la connexion est également désactivé pour éviter d'autres requêtes sur la même connexion.
Observabilité
nftset_stats
Contexte : location
Par défaut : —
Active le point de terminaison des statistiques JSON.
location = /_stats {
nftset_stats;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Voir JSON Stats API pour le format de réponse.
nftset_metrics
Contexte : location
Par défaut : —
Active le point de terminaison des métriques Prometheus.
location = /metrics {
nftset_metrics;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Voir Prometheus Metrics pour les métriques disponibles.
📝 Variables NGINX
Le module expose deux variables à utiliser dans les journaux, les en-têtes ou les conditionnels.
$nftset_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ée (mode dry-run) |
ratelimited |
Limite de taux dépassée |
challenged |
Page de défi servie |
$nftset_matched_set
Nom de l'ensemble nft qui a correspondu (le cas échéant), au format table:setname. 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'ensemble nft. Si vous vérifiez l'ensemble nft manuellement et ne trouvez pas l'IP : - L'entrée peut avoir expiré (les ensembles nft prennent en charge les délais d'expiration par entrée) - Le cache du module (par défaut 60s) peut montrer une entrée récemment retirée comme toujours correspondante - Quelque chose peut avoir retiré l'entrée après que la requête a é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 '
'nftset_result="$nftset_result" '
'matched_set="$nftset_matched_set"';
access_log /var/log/nginx/security.log security;
Ajouter des en-têtes pour le débogage :
add_header X-NFTSet-Result $nftset_result always;
add_header X-NFTSet-Matched $nftset_matched_set always;
Journalisation conditionnelle :
# Journaliser uniquement les requêtes bloquées
map $nftset_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_nftset_requests_total Total des requêtes traitées
# TYPE nginx_nftset_requests_total counter
nginx_nftset_requests_total{result="checked"} 1234567
nginx_nftset_requests_total{result="allowed"} 1234000
nginx_nftset_requests_total{result="blocked"} 500
nginx_nftset_requests_total{result="error"} 67
# HELP nginx_nftset_cache_total Opérations de cache
# TYPE nginx_nftset_cache_total counter
nginx_nftset_cache_total{result="hit"} 1200000
nginx_nftset_cache_total{result="miss"} 34567
# HELP nginx_nftset_cache_entries Entrées de cache actuelles
# TYPE nginx_nftset_cache_entries gauge
nginx_nftset_cache_entries 5432
# HELP nginx_nftset_autoadd_total Opérations d'auto-ajout
# TYPE nginx_nftset_autoadd_total counter
nginx_nftset_autoadd_total{result="success"} 42
nginx_nftset_autoadd_total{result="failed"} 3
# HELP nginx_nftset_ratelimit_total Événements de limitation de taux
# TYPE nginx_nftset_ratelimit_total counter
nginx_nftset_ratelimit_total{action="triggered"} 156
nginx_nftset_ratelimit_total{action="autobanned"} 23
# HELP nginx_nftset_challenge_total Événements de défi
# TYPE nginx_nftset_challenge_total counter
nginx_nftset_challenge_total{result="issued"} 1000
nginx_nftset_challenge_total{result="passed"} 950
nginx_nftset_challenge_total{result="failed"} 50
# HELP nginx_nftset_uptime_seconds Temps de fonctionnement du module
# TYPE nginx_nftset_uptime_seconds gauge
nginx_nftset_uptime_seconds 86400
Requêtes du tableau de bord Grafana
Taux de requêtes par résultat :
rate(nginx_nftset_requests_total[5m])
Taux de blocage :
rate(nginx_nftset_requests_total{result="blocked"}[5m])
Taux de réussite du cache :
rate(nginx_nftset_cache_total{result="hit"}[5m]) /
(rate(nginx_nftset_cache_total{result="hit"}[5m]) + rate(nginx_nftset_cache_total{result="miss"}[5m]))
Déclenchements de limite de taux par minute :
rate(nginx_nftset_ratelimit_total{action="triggered"}[1m]) * 60
📈 JSON Stats API
Le point de terminaison /_stats retourne des statistiques détaillées au format JSON.
Format de réponse
{
"version": "3.0.0",
"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'ensemble nft |
cache.hits |
Hits de cache (évité appel au noyau) |
cache.misses |
Misses 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 honeypot réussis |
autoadd.failed |
Échecs d'ajouts honeypot |
ratelimit.triggered |
Violations de limite de taux |
ratelimit.autobanned |
IPs ajoutées automatiquement à la liste de bannissement |
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 │ │
│ └───────┬───────┘ │
│ │ Passé │
│ ▼ │
│ ┌───────────────┐ ┌─────────────┐ │
│ │ Vérification │────▶│ HIT │────▶ Utiliser le résultat mis en cache │
│ └───────┬───────┘ └─────────────┘ │
│ │ MISS │
│ ▼ │
│ ┌───────────────┐ │
│ │ Requête nft │──── Contexte libnftables local au thread │
│ │ (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'ensemble nft │
│ │ 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 | But |
|---|---|---|
| Contexte libnftables | Local au thread | Contexte 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 une table nft et un ensemble
sudo nft add table ip filter
sudo nft add set ip filter blacklist '{ type ipv4_addr; }'
sudo nft add element ip filter blacklist '{ 1.2.3.4 }'
server {
listen 80;
nftset_blacklist filter:blacklist;
location / {
root /var/www/html;
}
}
Exemple 2 : API avec limitation de taux
server {
listen 80;
# Limitation stricte de taux pour l'API
nftset_ratelimit rate=100 window=1m autoban=filter:api_banned ban_time=3600;
# Autoriser uniquement les partenaires connus
nftset_whitelist filter:api_partners;
nftset_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
nftset_blacklist filter:malware_ips filter:tor_exits filter:datacenter_ranges;
nftset_status 444;
nftset_cache_ttl 5m;
# Couche 2 : Limitation de taux
nftset_ratelimit rate=60 window=1m autoban=filter:ratelimited ban_time=1800;
# Couche 3 : Défi bot
nftset_challenge on;
nftset_challenge_difficulty 2;
# Contenu réel
location / {
root /var/www/html;
}
# Pièges honeypot - retourne 404 (par défaut) pour sembler être des fichiers manquants
location ~ ^/(wp-admin|phpmyadmin|admin)\.php$ {
nftset_autoadd filter:honeypot timeout=86400;
}
# Surveillance
location = /metrics {
nftset_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
nftset_blacklist filter:new_threat_list;
nftset_dryrun on;
location / {
root /var/www/html;
}
}
Vérifiez les journaux :
tail -f /var/log/nginx/error.log | grep "DRYRUN"
Exemple 5 : Liste blanche CIDR (plages réseau)
# Créer un ensemble d'intervalles pour les plages CIDR
sudo nft add table ip filter
sudo nft add set ip filter trusted '{ type ipv4_addr; flags interval; }'
sudo nft add element ip filter trusted '{ 192.168.1.0/24, 10.0.0.0/8 }'
# Version IPv6
sudo nft add table ip6 filter
sudo nft add set ip6 filter trusted6 '{ type ipv6_addr; flags interval; }'
sudo nft add element ip6 filter trusted6 '{ 2001:db8::/32 }'
server {
listen 80;
# Liste blanche de réseaux entiers
nftset_whitelist filter:trusted;
location / {
root /var/www/html;
}
}
🔧 Dépannage
Module non chargé
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.
Ensemble nft non trouvé
nftset: set 'filter:myset' does not exist
Solution : Créez la table nft et l'ensemble avant de démarrer NGINX :
sudo nft add table ip filter
sudo nft add set ip filter myset '{ type ipv4_addr; }'
ASTUCE : Listez les ensembles disponibles avec :
nft list sets
Permission refusée
nftset: 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'utiliser netlink_netfilter_socket
Solution : Installez le module de politique SELinux inclus :
cd selinux/
sudo ./install.sh
Ou manuellement :
# Vérifier
semodule -l | grep nginx_nftset
La politique permet à httpd_t (le domaine SELinux de NGINX) d'utiliser les sockets netlink_netfilter requis par libnftables.
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'ensemble nft pour l'auto-interdiction existe et a un support de délai d'expiration :
sudo nft add table ip filter
sudo nft add set ip filter ratelimited '{ type ipv4_addr; flags timeout; timeout 1h; }'
Le journal montre "matched=table:setname" mais l'IP n'est pas dans l'ensemble nft
C'est un comportement attendu. Le module rapporte ce qu'il a vu au moment de la requête. Si vous vérifiez l'ensemble nft plus tard et ne trouvez pas l'IP :
-
Expiration du délai : L'IP a été ajoutée avec un délai et a depuis expiré
# Vérifiez les drapeaux de l'ensemble nft list set ip filter setname # Recherchez "flags timeout" dans la sortie -
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ésactivez temporairement le cache pour le débogage (pas pour la production !) nftset_cache_ttl 0; -
L'entrée a été retirée : fail2ban, des scripts ou des commandes manuelles peuvent l'avoir retirée
-
Problème de configuration de piège : Si vous utilisez des pièges honeypot avec
nftset_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). Utilisezrobots.txtpour exclure les chemins de piège du crawl.
autoadd échoue avec une erreur de délai
Cela signifie que vous utilisez timeout=N dans nftset_autoadd mais que l'ensemble nft a été créé sans support de délai d'expiration.
Solution : Recréez l'ensemble nft avec un support de délai d'expiration :
# Supprimer et recréer avec le drapeau de délai
sudo nft delete set ip filter honeypot
sudo nft add set ip filter honeypot '{ type ipv4_addr; flags timeout; timeout 1d; }'
🔄 Migration depuis ipset-access
Si vous migrez depuis l'ancien ngx_http_ipset_access_module, suivez ces étapes :
1. Convertir les ipsets en ensembles nft
# Ancien ipset
ipset create bad_guys hash:ip timeout 86400
# Nouvel ensemble nft équivalent
nft add table ip filter
nft add set ip filter bad_guys '{ type ipv4_addr; flags timeout; timeout 1d; }'
# Pour les plages CIDR (hash:net → drapeau d'intervalle)
# Ancien : ipset create networks hash:net
# Nouveau :
nft add set ip filter networks '{ type ipv4_addr; flags interval; }'
2. Mettre à jour la configuration NGINX
| Ancien (ipset) | Nouveau (nftset) |
|---|---|
ipset_blacklist bad_guys; |
nftset_blacklist filter:bad_guys; |
ipset_whitelist trusted; |
nftset_whitelist filter:trusted; |
ipset_autoadd honeypot timeout=3600; |
nftset_autoadd filter:honeypot timeout=3600; |
ipset_ratelimit rate=100 autoban=ratelimited; |
nftset_ratelimit rate=100 autoban=filter:ratelimited; |
ipset_challenge on; |
nftset_challenge on; |
ipset_challenge_difficulty 3; |
nftset_challenge_difficulty 3; |
ipset_dryrun on; |
nftset_dryrun on; |
ipset_fail_open on; |
nftset_fail_open on; |
ipset_cache_ttl 60s; |
nftset_cache_ttl 60s; |
ipset_status 403; |
nftset_status 403; |
ipset_stats; |
nftset_stats; |
ipset_metrics; |
nftset_metrics; |
$ipset_result |
$nftset_result |
$ipset_matched_set |
$nftset_matched_set |
3. Mettre à jour les formats de journal
# Ancien
log_format security '... ipset_result="$ipset_result" matched_set="$ipset_matched_set"';
# Nouveau
log_format security '... nftset_result="$nftset_result" matched_set="$nftset_matched_set"';
4. Mettre à jour les requêtes Prometheus/Grafana
| Ancienne métrique | Nouvelle métrique |
|---|---|
nginx_ipset_requests_total |
nginx_nftset_requests_total |
nginx_ipset_cache_total |
nginx_nftset_cache_total |
nginx_ipset_cache_entries |
nginx_nftset_cache_entries |
nginx_ipset_autoadd_total |
nginx_nftset_autoadd_total |
nginx_ipset_ratelimit_total |
nginx_nftset_ratelimit_total |
nginx_ipset_challenge_total |
nginx_nftset_challenge_total |
nginx_ipset_uptime_seconds |
nginx_nftset_uptime_seconds |
5. Différences clés
| Fonctionnalité | ipset-access | nftset-access |
|---|---|---|
| Backend | libipset (ipsets du noyau) | libnftables (nftables) |
| Format d'ensemble | setname |
table:setname |
| Ensembles CIDR | type hash:net |
drapeau flags interval |
| Famille | Spécifiée dans le type d'ensemble | Auto-détectée à partir de l'IP du client |
| firewalld | Backend iptables uniquement | Compatible avec le backend nftables |
Pourquoi migrer ?
- Compatibilité RHEL 9/Rocky 9 : firewalld par défaut utilise le backend nftables
- Support moderne du noyau : nftables est l'avenir du pare-feu Linux
- Gestion unifiée : Utilisez les commandes
nftpour le pare-feu et le contrôle d'accès - Meilleur support CIDR : Les ensembles d'intervalles gèrent efficacement les plages réseau
📋 Exigences
- NGINX ≥ 1.22 (construit avec
--with-compat) - Noyau Linux avec support nftables
- Bibliothèque et en-têtes de développement libnftables
- Capacités :
CAP_NET_ADMINpour les opérations nftables
📜 Licence
Il s'agit d'un logiciel propriétaire. Tous droits réservés.
Disponible exclusivement via le GetPageSpeed Premium Repository.
👤 Auteur
Danila Vershinin GetPageSpeed LLC
🆘 Support
- Honeypot v2.0 Utiliser nftset-access pour interdire automatiquement les bots
- Support : Disponible pour les abonnés premium
- Contact : GetPageSpeed Support
Module d'accès NGINX NFTSet
Un module NGINX premium par GetPageSpeed LLC
www.getpagespeed.com