Bloquer le trafic par pays sous Linux : GeoIP, nftables | INTROSERV
EUR
european

EUR

usa

USD

French Fr
Ex. VAT Ex. VAT 0%

Comment bloquer le trafic par pays sur un pare-feu Linux avec des règles GeoIP

Niveau : Professionnel
Durée estimée : ~35 minutes
Objectif : Configurer des règles de pare-feu GeoIP sur un serveur Linux pour restreindre l'accès par pays, avec iptables et le module xtables-geoip ou avec nftables et des ensembles d'adresses IP (IP sets) – et automatiser les mises à jour afin que les listes restent à jour.

Introduction

Si vos services ciblent une région précise, il n'y a aucune raison d'accepter du trafic en provenance du reste du monde. Le géoblocage sur un pare-feu Linux permet de rejeter les paquets selon leur pays d'origine avant qu'ils n'atteignent votre application – ce qui réduit le bruit des attaques par force brute et la surface d'attaque. Dans ce tutoriel, vous allez bloquer le trafic par pays sur un pare-feu Linux à l'aide de règles GeoIP : d'abord avec iptables et xtables-addons, puis avec nftables et des ensembles d'adresses IP basés sur CIDR, avec mises à jour automatiques de la base de données pour que votre blocage d'adresses IP par pays reste précis.

Prérequis

Avant de commencer, assurez-vous que les conditions suivantes sont remplies :

  • Système d'exploitation : Ubuntu 22.04/24.04 LTS, Debian 12/13, AlmaLinux/RHEL 9/10
  • Accès : accès sudo ou root au serveur
  • Pare-feu : iptables 1.8+ avec xtables-addons, ou nftables 1.0+
  • Paquets requis : curl, iptables, linux-headers-$(uname -r) (Debian/Ubuntu) ; dépôt EPEL activé (RHEL/AlmaLinux 9)

Info

Sur Debian 12+, Ubuntu 22.04+ et RHEL/AlmaLinux 9+, la commande iptables est une surcouche du moteur nftables (iptables-nft). La correspondance -m geoip fonctionne correctement avec ce moteur.

  • Réseau : une idée claire des pays dont vos services doivent accepter le trafic
  • Connaissances requises : maîtrise de la ligne de commande Linux, notions de base sur les pare-feu et édition de fichiers
  • Accès de secours : une console hors bande (out-of-band, IPMI/KVM) opérationnelle ou le mode de secours (rescue mode) de l'hébergeur, au cas où une règle vous verrouillerait l'accès

Warning

Appliquer des règles de pare-feu par pays au travers d'une session SSH est intrinsèquement risqué. Si vous bloquez votre propre pays par erreur, vous perdez l'accès. Prévoyez toujours un accès de secours hors bande et testez les règles avant de les rendre permanentes.

Étape 1 : Identifier les pays autorisés et bloqués

Avant de toucher au pare-feu, définissez votre politique. Il existe deux approches :

  • Liste d'autorisation (recommandée) : N'autoriser que les pays dont vous avez besoin et rejeter tout le reste. C'est plus strict et plus sûr.
  • Liste de blocage : Tout autoriser et rejeter certains pays. Plus simple, mais cela laisse une surface d'attaque plus grande.

Dans ce tutoriel, nous utiliserons l'approche par liste d'autorisation, conforme au principe du moindre privilège. Supposons que vos services ne desservent que des utilisateurs des États-Unis, d'Allemagne et de Pologne. Les codes pays ISO à deux lettres sont : US, DE, PL.

Info

Les codes pays suivent la norme ISO 3166-1 alpha-2. Retrouvez la liste complète sur https://www.iso.org/obp/ui/#search/code/. Soyez précis : une faute de frappe ici bloque silencieusement du trafic légitime.

Étape 2 : Configurer GeoIP avec iptables (xtables-addons)

Cette méthode utilise le module xt_geoip de xtables-addons, qui ajoute à iptables la correspondance -m geoip. C'est l'une des méthodes les plus éprouvées pour bloquer une plage d'adresses IP par pays sous Linux.

2.1 Installer xtables-addons et ses dépendances

Debian/Ubuntu :

sudo apt install -y linux-headers-$(uname -r) sudo apt update && sudo apt install -y \ xtables-addons-common libtext-csv-xs-perl unzip iptables curl

Warning

xtables-addons n'est pas disponible dans les dépôts d'AlmaLinux 10. Utilisez plutôt la méthode nftables (Étape 3) ou compilez xtables-addons à partir des sources.

Après l'installation, vérifiez que le module est disponible :

modinfo xt_geoip

La sortie attendue contient une ligne du type :

filename: /lib/modules/.../xt_geoip.ko description: Xtables: country matching via GeoIP

Si modinfo renvoie une erreur, le module n'a pas été installé correctement. Vérifiez que les en-têtes du noyau correspondent à la version du noyau en cours d'exécution.

2.2 Télécharger et construire la base de données GeoIP

Le module xt_geoip nécessite une base de données locale des correspondances pays-IP. Elles sont distribuées sous forme de fichiers CSV et doivent être converties au format binaire.

Créez le répertoire de travail et le répertoire de la base de données :

sudo mkdir -p /usr/share/xt_geoip

Téléchargez les dernières données GeoIP au format CSV. La source amont fournit les données via l'outillage xtables-addons :

cd /tmp /usr/libexec/xtables-addons/xt_geoip_dl

Convertissez le CSV téléchargé au format binaire :

/usr/libexec/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip *.csv

Sortie attendue – une liste des codes pays traités :

4540 IPv4 ranges for ZA 1071 IPv6 ranges for ZA 147 IPv4 ranges for ZW 94 IPv6 ranges for ZW ...

2.3 Appliquer les règles iptables avec correspondance GeoIP

Créez maintenant les règles de pare-feu GeoIP proprement dites. Le script suivant autorise le trafic des pays choisis et rejette tout le reste sur la chaîne INPUT.

Sauvegardez d'abord vos règles actuelles :

sudo iptables-save > /tmp/iptables-backup-$(date +%Y%m%d).rules

Appliquez la liste d'autorisation des pays :

# Allow loopback sudo iptables -A INPUT -i lo -j ACCEPT # Allow established and related connections sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Allow traffic from US, DE, PL only sudo iptables -A INPUT -m geoip --src-cc US,DE,PL -j ACCEPT # Log dropped packets sudo iptables -A INPUT -j LOG --log-prefix "GEOIP-DROP: " --log-level 4 # Drop everything else sudo iptables -A INPUT -j DROP

Warning

La règle DROP finale bloque tout le trafic qui ne correspond pas à la liste d'autorisation. Assurez-vous que le pays d'origine de votre connexion SSH est inclus, sinon vous serez immédiatement déconnecté sans pouvoir revenir. En cas de doute, ajoutez une règle ACCEPT temporaire pour votre adresse IP avant le DROP : sudo iptables -I INPUT -s <YOUR_IP_ADDRESS> -j ACCEPT.

Vérifiez que les règles sont actives :

sudo iptables -L INPUT -v --line-numbers

Sortie attendue :

Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT all -- anywhere anywhere /* loopback */ 2 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED 3 ACCEPT all -- anywhere anywhere -m geoip --source-country US,DE,PL 4 LOG all -- anywhere anywhere LOG level warning prefix "GEOIP-DROP: " 5 DROP all -- anywhere anywhere

2.4 Rendre les règles iptables persistantes après redémarrage

Les règles appliquées avec iptables sont perdues au redémarrage. Enregistrez-les :

Debian/Ubuntu :

sudo apt install iptables-persistent -y sudo netfilter-persistent save

AlmaLinux/RHEL :

sudo service iptables save

Étape 3 : Configurer GeoIP avec nftables (ensembles IP)

Si votre système utilise nftables (par défaut sur Debian 11+, Ubuntu 22.04+ et RHEL 9+), vous pouvez obtenir le même résultat avec des ensembles d'adresses IP (IP sets) alimentés par des blocs CIDR au niveau des pays. Cette approche ne nécessite aucun module noyau en dehors de ceux que nftables fournit déjà.

3.1 Obtenir les plages d'adresses IP par pays

Téléchargez les listes CIDR des pays que vous souhaitez autoriser. Plusieurs sources publiques les fournissent, comme ipdeny.com :

sudo mkdir -p /etc/nftables/geoip cd /etc/nftables/geoip # Download CIDR blocks for US, DE, PL for CC in us de pl; do sudo curl -sS -o /etc/nftables/geoip/${CC}.zone \ "https://www.ipdeny.com/ipblocks/data/aggregated/${CC}-aggregated.zone"; done

Vérifiez que les fichiers contiennent des plages CIDR :

head -5 /etc/nftables/geoip/us.zone

Sortie attendue (plages CIDR, une par ligne) :

1.178.0.0/23 1.178.4.0/22 1.178.8.0/21 ...

3.2 Construire et charger la configuration nftables

Créez un script qui lit les fichiers CIDR et génère un ensemble nftables. Enregistrez-le sous /etc/nftables/geoip-update.sh :

sudo nano /etc/nftables/geoip-update.sh

Collez le contenu suivant :

#!/bin/bash # Generate nftables set from country CIDR files set -euo pipefail GEOIP_DIR="/etc/nftables/geoip" OUTPUT="/etc/nftables/geoip-sets.nft" echo "define ALLOWED_COUNTRIES = {" > "$OUTPUT" for zone_file in "$GEOIP_DIR"/*.zone; do while IFS= read -r cidr; do && continue echo " ${cidr}," >> "$OUTPUT" done < "$zone_file" done echo "}" >> "$OUTPUT" echo "GeoIP set generated: $(wc -l < "$OUTPUT") lines"

Rendez-le exécutable :

sudo chmod +x /etc/nftables/geoip-update.sh

Exécutez le script :

sudo /etc/nftables/geoip-update.sh

Référencez maintenant cet ensemble dans votre configuration nftables :

# Debian/Ubuntu: sudo nano /etc/nftables.conf # AlmaLinux/RHEL: sudo nano /etc/sysconfig/nftables.conf

Ajoutez l'instruction include et utilisez l'ensemble dans votre chaîne input :

#!/usr/sbin/nft -f flush ruleset include "/etc/nftables/geoip-sets.nft" table inet filter { chain input { type filter hook input priority 0; policy drop; ct state invalid drop iif lo accept ct state established,related accept # Allow ICMP ip protocol icmp accept ip6 nexthdr icmpv6 accept # GeoIP: allow only listed countries ip saddr $ALLOWED_COUNTRIES accept # Log dropped packets log prefix "geoip-drop: " level info # Everything else is dropped by policy } chain forward { type filter hook forward priority 0; policy drop; } chain output { type filter hook output priority 0; policy accept; } }

Vérifiez la syntaxe avant l'application :

sudo nft -c -f /etc/nftables.conf

Si aucune erreur n'apparaît, appliquez et vérifiez :

sudo nft -f /etc/nftables.conf sudo systemctl enable --now nftables sudo nft list ruleset | head -20

Tip

Pour de très grands ensembles d'adresses IP (plus de 100 000 entrées), nftables s'en sort nettement mieux qu'iptables. La correspondance par ensembles de nftables utilise en interne des tables de hachage (hash maps) ; les performances de recherche restent donc constantes quelle que soit la taille de l'ensemble.

Étape 4 : Automatiser les mises à jour de la base de données GeoIP

Les correspondances adresse IP-pays évoluent en permanence. Une base de données vieille d'un mois comportera des lacunes. Planifiez des mises à jour automatiques avec cron.

4.1 Créer le script de mise à jour

Créez /usr/local/sbin/geoip-refresh.sh :

sudo nano /usr/local/sbin/geoip-refresh.sh

Pour iptables (xtables-addons) :

#!/bin/bash set -euo pipefail cd /tmp /usr/libexec/xtables-addons/xt_geoip_dl /usr/libexec/xtables-addons/xt_geoip_build \ -D /usr/share/xt_geoip *.csv rm -f /tmp/*.csv /tmp/*.zip logger "GeoIP database updated successfully"

Pour nftables :

#!/bin/bash set -euo pipefail GEOIP_DIR="/etc/nftables/geoip" for CC in us de pl; do curl -sS -o "${GEOIP_DIR}/${CC}.zone" \ "https://www.ipdeny.com/ipblocks/data/aggregated/${CC}-aggregated.zone" done /etc/nftables/geoip-update.sh systemctl reload nftables logger "GeoIP nftables sets updated and reloaded"

Rendez-le exécutable :

sudo chmod +x /usr/local/sbin/geoip-refresh.sh

4.2 Planifier avec cron

Avant de planifier la tâche cron, assurez-vous que le service nftables est activé et en cours d'exécution (si vous utilisez la méthode nftables) :

sudo systemctl enable --now nftables

Exécutez la mise à jour chaque semaine :

sudo crontab -e

Ajoutez :

0 3 * * 0 /usr/local/sbin/geoip-refresh.sh >> /var/log/geoip-update.log 2>&1

Cette tâche s'exécute chaque dimanche à 3 h 00. Après la première exécution planifiée, vérifiez qu'elle a fonctionné :

cat /var/log/geoip-update.log

Étape 5 : Vérification et tests

5.1 Tester depuis un pays autorisé

Depuis une machine située dans l'un des pays autorisés, connectez-vous en SSH ou envoyez une requête HTTP :

curl -v http://<YOUR_SERVER_IP>

La connexion devrait aboutir normalement.

5.2 Simuler un pays bloqué

Utilisez curl avec une adresse IP connue d'un pays bloqué via un proxy, ou testez en local en retirant temporairement votre propre pays de la liste d'autorisation puis en tentant une connexion depuis un second terminal.

Info

Des services en ligne comme https://ipinfo.io permettent de vérifier dans quel pays une adresse IP donnée est enregistrée. Utilisez curl https://ipinfo.io/<YOUR_IP_ADDRESS> pour confirmer.

5.3 Vérifier les compteurs du pare-feu

iptables :

sudo iptables -L INPUT -v -n

Regardez les compteurs de paquets de la règle DROP : ils doivent s'incrémenter à mesure que le trafic bloqué arrive.

nftables :

sudo nft list chain inet filter input

5.4 Surveiller les journaux système

Recherchez les paquets rejetés dans le journal système :

sudo journalctl -k --since "1 hour ago" | grep -i "geoip-drop"

Warning

Si vous observez un grand nombre de messages du journal du noyau signalant des paquets rejetés et que votre système ne répond plus, une inondation de journalisation peut en être la cause. Dans le pire des cas, cela peut provoquer un kernel panic. Si vous avez configuré le paramètre crashkernel et le service kdump, un kernel panic produira un vidage sur incident (vmcore) dans /var/crash que vous pourrez analyser ultérieurement. Sans kdump, vous n'obtenez qu'un redémarrage et aucun diagnostic. Consultez la section ci-dessous pour un bref aperçu.

Étape 6 : Se protéger d'un kernel panic lors de modifications du pare-feu

Des modifications agressives du pare-feu sur un serveur de production très sollicité – notamment celles qui provoquent des pics de trafic soudains ou des inondations de journalisation – peuvent, dans de rares cas, entraîner un kernel panic. Si cela arrive et que vous ne vous êtes pas préparé, vous n'obtenez rien : seulement un redémarrage et aucune donnée sur la cause du problème.

Kdump est le mécanisme Linux standard pour capturer un vidage sur incident lorsqu'un kernel panic se produit. Il utilise kexec pour démarrer un noyau de capture secondaire (capture kernel), qui écrit l'image mémoire (vmcore) sur le disque avant le redémarrage du système.

Pour disposer d'éléments de diagnostic :

  1. Vérifiez que kdump est installé et activé. Sur RHEL/AlmaLinux, il est généralement préinstallé. Sur Debian/Ubuntu :

    sudo apt install kdump-tools kexec-tools -y

  2. Vérifiez que le paramètre crashkernel est défini dans la configuration de votre chargeur d'amorçage :

    cat /proc/cmdline | grep crashkernel

    Vous devriez voir quelque chose comme crashkernel=256M. S'il est absent, vous devez configurer le paramètre crashkernel dans GRUB et redémarrer. La quantité exacte de mémoire à réserver pour kdump sous Linux dépend de votre mémoire vive totale – 256M est une valeur par défaut sûre pour les serveurs disposant de 4 Go ou plus.

  3. Vérifiez que le service kdump est actif :

    sudo systemctl status kdump

Info

Si un kernel panic se produit, le système utilise kexec pour démarrer le noyau de capture, écrit le vmcore dans /var/crash, puis redémarre normalement. Vous pouvez ensuite effectuer une analyse de vmcore sous Linux avec l'utilitaire crash pour déterminer la cause première. Cela fait partie intégrante du dépannage d'un kernel panic sous Linux sur les systèmes de production. Pour un guide complet sur la façon d'activer kdump sous Linux et sur la configuration de kexec kdump sous Linux, reportez-vous à un tutoriel kdump dédié.

Dépannage

  • Accès SSH perdu : Utilisez la console hors bande (out-of-band) / le mode de secours (rescue mode).
  • modinfo xt_geoip : not found : Installez linux-headers-$(uname -r).
  • iptables: command not found (Debian 13) : Installez iptables avec sudo apt install iptables.
  • nftables.service is not active : Exécutez sudo systemctl enable --now nftables.
  • /etc/sysconfig/nftables.conf vide sur AlmaLinux : Utilisez ce chemin à la place de /etc/nftables.conf pour configurer les règles.

Retour arrière (Rollback)

Pour annuler le blocage par pays et rétablir l'accès ouvert :

iptables – restauration depuis la sauvegarde :

sudo iptables-restore < /tmp/iptables-backup-*.rules

Info

Si vous avez appliqué les règles GeoIP sur un serveur sans configuration de pare-feu préalable, le fichier de sauvegarde sera vide. Dans ce cas, utilisez les commandes de vidage et de politique ci-dessous à la place de iptables-restore.

Ou videz toutes les règles :

sudo iptables -F INPUT sudo iptables -P INPUT ACCEPT

Warning

Vider les règles en passant la politique sur ACCEPT supprime toute protection du pare-feu. Appliquez immédiatement après votre jeu de règles de sécurité standard.

nftables – restauration de la configuration par défaut :

sudo nft flush ruleset

Restaurez ensuite votre configuration nftables de base (sans GeoIP) :

sudo nft -f /etc/nftables.conf.backup

Pour supprimer complètement les composants GeoIP :

sudo rm -rf /etc/nftables/geoip sudo rm -f /etc/nftables/geoip-sets.nft /etc/nftables/geoip-update.sh sudo crontab -l | grep -v geoip-refresh | sudo crontab -

Supprimez xtables-addons (s'il est installé) :

Debian/Ubuntu :

sudo apt remove xtables-addons-common -y

AlmaLinux/RHEL :

sudo dnf remove xtables-addons -y

Conclusion

Votre serveur utilise désormais des règles de pare-feu GeoIP pour bloquer le trafic par pays sous Linux – soit avec iptables et xt_geoip, soit avec nftables et des ensembles d'adresses IP basés sur CIDR. La base de données se met à jour automatiquement, vous disposez d'un plan de retour arrière et, grâce à kdump configuré pour capturer un vidage sur incident en cas de kernel panic, votre environnement de production est couvert à la fois contre les menaces courantes et contre les pires scénarios.

Version du document : 1.0
Dernière mise à jour : mai 2026
Responsable : Équipe de documentation technique

VAT

  • Other

    Ex. VAT

    0%
  • austria

    Austria

    20%
  • Belgium

    Belgium

    21%
  • Bulgaria

    Bulgaria

    20%
  • Croatia

    Croatia

    25%
  • Cyprus

    Cyprus

    19%
  • Czech Republic

    Czech Republic

    21%
  • Denmark

    Denmark

    25%
  • Estonia

    Estonia

    22%
  • France

    France

    20%
  • Finland

    Finland

    24%
  • Germany

    Germany

    19%
  • Greece

    Greece

    24%
  • Hungary

    Hungary

    27%
  • Ireland

    Ireland

    23%
  • Italy

    Italy

    22%
  • Latvia

    Latvia

    21%
  • Lithuania

    Lithuania

    21%
  • Luxembourg

    Luxembourg

    17%
  • Malta

    Malta

    18%
  • Netherlands

    Netherlands

    21%
  • Poland

    Poland

    23%
  • Portugal

    Portugal

    23%
  • Romania

    Romania

    19%
  • Slovakia

    Slovakia

    20%
  • Slovenia

    Slovenia

    22%
  • Spain

    Spain

    21%
  • Sweden

    Sweden

    25%
  • USA

    USA

    0%
european
states
  • germany
  • Español
  • Italiano
  • Poland
  • Русский
  • Slovenski
  • Türkçe
  • ukraine
  • kingdom
  • French
  • Hrvatska
  • Other
  • Austria
  • Belgium
  • Bulgaria
  • Croatia
  • Cyprus
  • Czech Republic
  • Denmark
  • Estonia
  • Finland
  • France
  • Germany
  • Greece
  • Hungary
  • Ireland
  • Italy
  • Latvia
  • Lithuania
  • Luxembourg
  • Malta
  • Netherlands
  • Poland
  • Portugal
  • Romania
  • Slovakia
  • Slovenia
  • Spain
  • Sweden
  • USA