[Tutoriel] Bloquer l'accès à votre serveur à des pays

Publié le 19 mars 2025

Tutoriel IA Linux Sécurité

Bonjour à tous,

Bonne année 2024.. 2025, enfin bref, ça fait bien longtemps que j’ai rien posté ici !

Il y a quelques semaines, j’ai remarqué un usage anormal du CPU sur mon serveur principal, je vais faire part ici d’une mini analyse et ce que j’ai fait pour y remédier.

L’analyse

J’ai remarqué directement que l’instance Mariadb utilisée par Gitea était à 100% sur tous les cœurs. Je vais voir dans les logs de Traefik et je me rends compte que je prends plus de 800 requêtes par secondes depuis des jours (avec des bursts à plus de 1500 req/s) depuis beaucoup (vraiment beaucoup) d’adresses IP différentes (on ne parle pas de 10 voire 100 adresses, mais bien plus mais je n’ai plus les chiffres et pas le temps de reparcourir les logs …).

Or sur mon instance Gitea, je n’ai pas énormément de choses … Rien d’assez passionnant pour justifier autant de trafic.

Le user-agent utilisé est celui de Google Chrome et en creusant un peu plus sur les IPs, je vois que 95% viennent de Chine, 2% de Singapour, 2% de Hong Kong et 1% pour le reste du monde. En creusant encore plus, j’apprends que je ne suis pas du tout le seul dans ce cas et que ce sont des robots pour piller de la data afin d’entraîner des IA qui tapent tous azimuts des instances Gitea publiques.

Donc ils utilisent un user-agent qui leur permet de pas être détecté instantanément. Et ils ne respectent pas non plus le fichier robots.txt dont voici son contenu:

User-agent: *
Disallow: /

C’est assez clair, j’interdis tous les robots (comme le confirme le site robots-txt.com).

Les divers palliatifs

Couper l’instance

À ce moment-là, c’était plutôt l’heure pour moi d’aller me coucher, j’ai donc voulu passer mon instance Gitea en mode maintenance. C’est une simple page HTML qui indique que le service est en maintenance. Le tout servit par un serveur nginx. Comme la page de maintenance répondait encore plus vite (des réponses 200), le nombre de requêtes a augmenté, et le serveur nginx ne tenait pas la charge … J’ai donc coupé l’instance jusqu’au lendemain dans l’attente d’une solution plus pérenne.

Whitelisting avec Trafik

La première chose que j’ai faite le lendemain, c’est d’activer le middleware IPAllowList de Traefik. Rien de sorcier, j’ai autorisé les quelques IP nécessaires à mon besoin personnel. Je suis le seul utilisateur de mon instance mais certains dépôts sont publics, tant pis pour l’indisponibilité sur ce laps de temps (et je suis désolé si ça a gêné certaines personnes).

Ratelimit avec Traefik

J’ai ensuite mis en place le middleware RateLimit de Traefik dans le but de désactiver le plugin IpAllowList. Or c’est bête, mais comme je me faisais taper très fort, mes propres requêtes sur l’instance ne passaient pas … Ce n’est donc pas viable, mais je laisse ce ratelimit, ça ne mange pas de pain (et ça protège l’instance Mariadb et donc le CPU du serveur).

Blocage géographique avec Traefik

J’ai ensuite découvert le plugin GeoBlock (code source ici) donc l’objectif est de pouvoir blacklister (ou whitelister) des pays entiers.

Voilà ce que j’ai donc rajouté dans ma configuration statique de Traefik:

experimental:
  localPlugins:
    geoblock:
      moduleName: "github.com/PascalMinder/geoblock"

Et dans la configuration dynamique:

http:
  middlewares:
    geoblock-deny-countries:
      plugin:
        geoblock:
          silentStartUp: true
          allowLocalRequests: true
          logLocalRequests: false
          logAllowedRequests: false
          logApiRequests: false
          #logFilePath: "/geoblock.log"
          api: "https://get.geojs.io/v1/ip/country/{ip}"
          apiTimeoutMs: 750
          cacheSize: 250000
          forceMonthlyUpdate: false
          allowUnknownCountries: false
          unknownCountryApiResponse: "nil"
          blackListMode: true
          httpStatusCodeDeniedRequest: 404
          countries:
            - CN
            - HK
            - SG

Ensuite, il suffit de monter le dépôt geoblock dans /plugins-local/src/github.com/PascalMinder/geoblock (à la sauce Golang quoi, tout dépend de votre cas), et le middleware peut être rajouté aux routeurs HTTP côté Traefik.

Je n’aimais pas trop le fait de dépendre d’un service externe (GeoJS) mais ça fonctionnait bien, les requêtes provenant de Chine étaient bien bloquées.

J’ai essayé de jouer sur le code de retour, mais que ce soit du 401, 403, 404, 500, 501 ou encore 503, rien n’y faisait, je me prenais toujours autant de requêtes. C’était même pire, plus je répondais rapidement, plus je recevais de requêtes ..

En fouillant dans le code source du plugin, j’ai vu qu’il était possible de rajouter assez facilement un délai sur les requêtes provenant d’adresses IP bannies. J’ai donc fait une Pull Request (toujours ouverte si vous voulez la relire d’ailleurs !) puis j’ai rajouté delayOnDenyMs: 6000 dans la configuration dans le but de faire perdre du temps aux robots scrollant mon instance Gitea. Je suis descendu à 4 requêtes par secondes en moyenne avec ce mécanisme.

Blocage géographique au niveau pare-feu

C’est là qu’OpenOffice … euh mon pare-feu entre en jeu.

Gros bémol, ça va bloquer l’accès à toutes les IP provenant de Chine à tous les services de mon serveur. Donc les requêtes légitimes (provenant d’êtres humains) sont également bloquées … (c’était déjà le cas avec la solution précédente, mais uniquement sur les services sur mon instance Gitea).

Bref, je suis désolé si des gens sont impactés … si vous êtes en Chine, j’imagine que vous avez des VPN donc ça devrait le faire, sinon contactez-moi et on voit pour whitelister votre adresse IP.

Pour commencer, je ne veux pas me baser sur un service externe et faire une requête pour interroger la provenance de chaque adresse IP (comme le fait le plugin Geoblock). Il existe des bases de données qui compilent déjà tout ça, autant en profiter. Mon choix s’est porté sur la base Geolite2-country de MaxMind.

Cette base est d’ailleurs compilée dans un dépôt sur Github: ip-location-db et accessible en lien direct en CSV ici.

J’ai ensuite fait un script python pour:

  • Télécharger la base.
  • Extraire les IP de début et fin de chaque bloc pour les pays choisis.
  • Convertir des IP en blocs CIDR (IP/masque) plus classiques (et surtout indispensable pour la suite).
  • Créer un ipset pour chaque pays avec tous les blocs à bloquer.
  • Ajouter ces ipset à iptables.

Ce script nécessite ipset et iptables sur votre machine ainsi que le module requests dans votre virtualenv python. Il est accessible ici pour les plus curieux. Bien sûr, on pourrait rendre ce script beaucoup plus propre et aller beaucoup plus loin, mais je n’ai ni le temps, ni l’envie.

Je l’ai fait en python par simplicité pour convertir les IP provenant du CSV en CIDR.

Conclusion

Il ne me reste plus qu’à attendre patiemment que la bulle IA explose. Ensuite, ces robots invasifs disparaitront petit à petit et il ne sera plus nécessaire de bloquer des pays entiers (encore désolé si ça vous impacte).

Le CPU de mon serveur se la coule douce depuis que j’ai appliqué ce script (je le lance désormais une fois par semaine depuis une crontab).

Pour finir, j’ai du monitoring pour savoir si mes services sont UP (grâce à Uptime Kuma), mais je vais devoir en rajouter sur l’usage CPU, disque, RAM de mon serveur … (histoire de ne pas découvrir ça au hasard sur la commande htop …).

Commentaires




Recettes de gourmands


Glace Spéculoos

Un excellent moyen de se rafraîchir tout en gourmandise.

via cooking.pofilo.fr le 23 juillet 2024

Purée

Un minimum d'ingrédients mais une texture parfaite.

via cooking.pofilo.fr le 15 mai 2024

Meringues

Pratique pour utiliser des blancs d'œufs, car les ingrédients sont au tant pour tant.

via cooking.pofilo.fr le 21 mars 2024

Généré avec openring