Comment bloquer un pays avec le firewall Linux

Beaucoup de trafic malveillant (bot, scan, attack) provient de pays qui n'offrent pas beaucoup de valeur commerciale.
Par exemple, la Chine, la Russie, etc.
On peut donc être amené à vouloir mettre certains pays en liste noire afin de bloquer les connexions provenant de ces pays.
Comment puis-je simplement configurer IPTABLES pour simplement refuser les connexions à certains pays ?
Dans ce tutoriel, je vous donne trois méthodes pour blacklister les adresses IP par pays :

  • ipset-country : un script qui créé des chaînes ipset et règles iptables afin de bloquer les pays de votre choix
  • manuellement avec ipset : vous créez les chaînes et les règles iptables pour bloquer totalement le trafic provenant de pays ou seulement certains ports réseau
  • avec xt_geoip : On ajoute le module geoip à iptables pour créer les règles souhaités

Les deux premières méthodes utilisent la base de données ipdeny.com qui regroupe tous les blocs d'IP par pays.
Enfin la dernière méthode utilise la base de données geoip de MaxMind.
Principalement le tutoriel montre comment mettre en place cela sur une distribution Linux à base de Debian (Ubuntu, Mint, ...).

Comment bloquer un pays avec le firewall Linux

Comment bloquer un pays avec le firewall Linux

avec ipset-country

ipset-country est un script de Github qui télécharge les zones des pays depuis ipdeny.com, créer les règles ipset et iptables pour bloquer des pays.
Vous pouvez configurer le pays à mettre en liste noir.
Il peut aussi fonctionner avec Firewalld et UFW (mais pas complètement supporté).
Enfin il fonctionne en service ou peut être exécuté manuellement.

C'est une solution très simple et automatiser pour mettre en place un blacklist de pays sur votre machine Linux.

  • Installer ipset avec APT :
sudo apt install ipset
Installer le paquet ipset par APT
  • Téléchargez le script ipset-country à placer dans /usr/sbin/ipset-country (par exemple)
sudo wget https://raw.githubusercontent.com/mkorthof/ipset-country/master/ipset-country -O /usr/sbin/ipset-country
Téléchargez le script ipset-country
  • Editez le script pour modifier la configuration
  • Commencez par définir les pays à bloquer sur le firewall dans la variable Country, sous la forme code ISO-3166-1, Nom. Voir aussi le site ipdeny.com
COUNTRY="CN,China; RU,Russia"
  • IPTABLES et IPSET sont utilisés par défaut pour créer les chaînes, les règles et les ipset. Définissez la cible à utiliser lorsque IP correspond à Pays: "Accepter", "Drop" ou "Reject". La valeur par défaut est MODE = "Reject"
# Iptables
MODE="reject" # Set target to use when ip matches country [accept|drop|reject]
RESTORE=0     # Run iptables-restore first, before adding rules [0/1]
LOGIPS=1      # Create logips chain to log matches [0/1]
  • Si le Firewalld Frontend ou UFW sont utilisés, vous pouvez l'activer toutefois UFW est mal supporté. Deux modes sont possibles :
  • BlackList : Bloquer les pays spécifiés, le mode défini sur "Reject" ou "Drop"
  • Whitelist : Autoriser les pays spécifiés et bloquer tous les autres, définir "Accepter"
FIREWALLD=0       # Use firewalld instead [0/1]
FIREWALLD_MODE=0  # Set 0 for default Blacklist (drop), or 1 to Whitelist [0/1]
FIREWALLD_RH8=0   # Enable firewalld on CentOS/RHEL 8, at your own risk [0/1]

UFW=0 # Set to 1 to use iptables besides ufw, at your own risk [0/1]
Configurer le script ipset-country pour bloquer des pays sur le firewall Linux
  • Puis on créé le service avec l'option -i
  • Puis on exécute le script, cela va prendre du temps car les règles de filtrages des pays se créent
/usr/sbin/ipset-country -i
systemctl start ipset-country
Installer ipset-country en service

Notez toutefois que l'on peut aussi exécuter le script directement.
Il est même possible de créer un fichier de configuration.

  • Vérifiez les logs dans /var/log/ipset-country.log
[email protected]:~$ cat /var/log/ipset-country.log
2021-11-20 09:33:04 ipset: NOK - NOT FOUND, exiting...
2021-11-20 09:33:34 zonefile: get "ipv4-cn-aggregated.zone" - OK
2021-11-20 09:33:34 ipset: create set "ipv4-china" - OK
2021-11-20 09:33:34 iptables: create log chain - OK
2021-11-20 09:33:34 iptables: append log rule - OK
2021-11-20 09:33:34 iptables: append reject rule - OK
2021-11-20 09:33:38 ipset: add "ipv4-cn-aggregated.zone" to "ipv4-china" - OK - 5244 entries
2021-11-20 09:33:38 iptables: insert ipset deny rule - OK
2021-11-20 09:33:39 zonefile: get "ipv4-ru-aggregated.zone" - OK
2021-11-20 09:33:39 ipset: create set "ipv4-russia" - OK
2021-11-20 09:33:46 ipset: add "ipv4-ru-aggregated.zone" to "ipv4-russia" - OK - 8443 entries
2021-11-20 09:33:46 iptables: insert ipset deny rule - OK
2021-11-20 09:33:46 zonefile: get "ipv6-cn.zone" - OK
2021-11-20 09:33:46 ipset: create set "ipv6-china" - OK
2021-11-20 09:33:46 ip6tables: create log chain - OK
2021-11-20 09:33:46 ip6tables: append log rule - OK
2021-11-20 09:33:46 ip6tables: append reject rule - OK
2021-11-20 09:33:48 ipset: add "ipv6-cn.zone" to "ipv6-china" - OK - 1803 entries
2021-11-20 09:33:48 ip6tables: insert ipset deny rule - OK
2021-11-20 09:33:48 zonefile: get "ipv6-ru.zone" - OK
2021-11-20 09:33:48 ipset: create set "ipv6-russia" - OK
2021-11-20 09:33:50 ipset: add "ipv6-ru.zone" to "ipv6-russia" - OK - 2347 entries
2021-11-20 09:33:50 ip6tables: insert ipset deny rule - OK
  • Dans le cas de l'utilisation d'ipset, on liste les chaînes, on voit ici que les chaînes pour bloquer la Chine et la Russie sont créées correctement
[email protected]:~$ sudo ipset -n list
ipv4-china
ipv4-russia
ipv6-china
ipv6-russia
  • Ainsi que les règles iptables grâce à la commande iptables-legacy-saves
:LOGIPS - [0:0]
-A INPUT -p tcp -m set --match-set ipv4-russia src -j LOGIPS
-A INPUT -p tcp -m set --match-set ipv4-china src -j LOGIPS
-A LOGIPS -m limit --limit 10/min -j LOG --log-prefix "IPS: " --log-level 6
-A LOGIPS -j REJECT --reject-with icmp-port-unreachable
  • Si tout va bien, vous devriez voir dans les logs (par exemple avec dmesg), les blocages des pays avec les logs IPS
Visualiser les blocages de pays dans iptables
  • Pour désinstaller le service ipset-country :
[email protected]:/home/debian# ./ipset-country -u
Warning: Stopping ipset-country.service, but it can still be activated by:
  ipset-country.timer
Removed /etc/systemd/system/timers.target.wants/ipset-country.timer.
rm: cannot remove '/lib/systemd/system/ipset-country.{service,timer}': No such file or directory

Vérifiez bien les logs, si les fichiers des zones de pays ne peuvent être téléchargés, des erreurs s'affichent et les chaînes ipset ne seront pas alimentées.

[email protected]:/data/script# cat /var/log/ipset-country.log
2021-11-20 10:38:27 zonefile: get "ipv4-cn-aggregated.zone" - OK
2021-11-20 10:38:27 zonefile: md5 "ipv4-cn-aggregated.zone" mismatch"
2021-11-20 10:38:27 zonefile: get "ipv4-ru-aggregated.zone" - OK
2021-11-20 10:38:27 zonefile: md5 "ipv4-ru-aggregated.zone" mismatch"
2021-11-20 10:38:28 zonefile: get "ipv6-cn.zone" - OK
2021-11-20 10:38:28 zonefile: md5 "ipv6-cn.zone" mismatch"
2021-11-20 10:38:28 zonefile: get "ipv6-ru.zone" - OK
2021-11-20 10:38:28 zonefile: md5 "ipv6-ru.zone" mismatch"
2021-11-20 10:38:55 zonefile: get "ipv4-cn-aggregated.zone" - SKIP
2021-11-20 10:38:55 zonefile: md5 "ipv4-cn-aggregated.zone" mismatch"
2021-11-20 10:38:56 zonefile: get "ipv4-ru-aggregated.zone" - SKIP
2021-11-20 10:38:56 zonefile: md5 "ipv4-ru-aggregated.zone" mismatch"
2021-11-20 10:38:56 zonefile: get "ipv6-cn.zone" - SKIP
2021-11-20 10:38:56 zonefile: md5 "ipv6-cn.zone" mismatch"
2021-11-20 10:38:57 zonefile: get "ipv6-ru.zone" - SKIP
2021-11-20 10:38:57 zonefile: md5 "ipv6-ru.zone" mismatch"
Bravo ! vous avez réussi à bloquer des pays sur le firewall Linux.

avec ipset et ipdeny.com

Dans cette seconde méthode on télécharge la base de données des blocs d'IP de pays sur le site ipdeny.com.
Ensuite on créé les chaînes ipset pour bloquer les connexions réseaux des pays souhaitées.
Ainsi, on blacklist chaque pays en utilisant cette base de données.

  • Tout d'abord, on installe ipset avec APT :
apt install ipset
Installer le paquet ipset par APT
  • On télécharge toutes les zones de pays depuis ipdeny :
wget --no-check-certificate http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz
  • Puis on créé la zone bk_pays dans ipset :
ipset create bk_pays hash:net
  • Puis on injecte les blocs d'IP dans notre chaîne ipset. Par exemple pour ajouter l'Ukraine (UA), remplacez le fichier de zone par le pays à bloquer :
for z_net in `cat ua.zone`; do ipset add bk_pays $z_net  ; done
Créer les règles ipset avec les blocs d'IP de blocages de pays
  • Enfin il ne reste plus qu'à créer les règles du firewall iptables pour faire correspondre à la chaîne bk_pays d'ipset. Par exemple pour bloquer entière le pays en entrée et sorties sur iptables :
iptables -A INPUT -m set --match-set bk_pays src -j ACCEPT
iptables -A OUTPUT -m set --match-set bk_pays dst -j ACCEPT

Ici on créé une seule chaîne avec tous les blocs d'IP mais il est bien entendu possible de créez une chaîne par pays, pour appliquer des règles iptables différentes.
Par exemple si vous cherchez à bloquer seulement certains ports réseaux.

Bravo ! vous avez réussi à bloquer des pays sur le firewall Linux.

avec xt_geoip

Cette dernière méthode consiste à installer un addons sur iptables afin de porter des fonctionnalités GeoIP.
Ensuite on télécharge la base de données Geoip de MaxMind.
Toutefois, celle-ci n'est plus en ligne mais on trouve une version encore à jour.

GeOIP est une collection d'IP correspondant aux emplacements géographiques où l'emplacement géographique est mappé avec les adresses IP attribuées à l'organisation, de la ville et des pays spécifiques. Les coordonnées géographiques dans la base de données GEOIP sont souvent près du centre de la population afin de ne pas être utilisées pour identifier une adresse ou un ménage particulière. Et avec l'aide d'un module appelé xt_geoip composé d'une extension IPTABLE Xtables-Addon et de la base de données GEOIP, nous effectuerons un filtrage de la circulation basé sur des pays qui nous aide à bloquer ou à autoriser le trafic d'un pays spécifique.

  • Installer les paquets suivants avec APT :
apt install xtables-addons-dkms xtables-addons-common libgeoip1 libtext-csv-xs-perl
Installer les paquets xtables-addons-dkms xtables-addons-common avec APT
  • Durant l'installation vérifiez bien que le modules Geoip se compile bien dans le noyau linux
Compilation du module xtables_addons dans le noyau Linux
  • Notamment à la fin le message DKMS: install completed doit être présent :
depmod......

DKMS: install completed.
Processing triggers for libc-bin (2.31-13+deb11u2) ...
Message DKMS: install completed
  • Ensuite on télécharge la base de données GeoIP de MaxMind et on la décompresse dans /usr/share/xt_geoip
wget -q https://legacy-geoip-csv.ufficyo.com/Legacy-MaxMind-GeoIP-database.tar.gz -O - | tar -xvzf - -C /usr/share/xt_geoip
Installation de la base de données GeoIP MaxMind dans xt_geoip
  • Si tout va bien, on peut créer les règles iptables de blocages avec le module geoip, en indiquant les pays par son code ISO-3166-1, par exemple ici la Chine, Hong-kong, Russie
iptables -A INPUT -m geoip --src-cc CN,HK,RU -j DROP
  • En version firewall-cmd cela donne :
firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -m geoip --src-cc IN,UN -j DROP

firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -m geoip ! --src-cc US -j DROP

firewall-cmd --direct --add-rule ipv4 filter OUTPUT 0 -m geoip --dst-cc IN -j DROP

Lorsque le module du kernel geoip ne se charge pas et donc le module n'est pas disponible pour iptables, cela retourne le message suivant :

iptables v1.8.7 (nf_tables): Couldn't load match `geoip':No such file or directory
Bravo ! vous avez réussi à bloquer des pays sur le firewall Linux.

Liens