IPv6, fail-fast et hardening : retour sur un ban Google de 24 h

Avril 2026, 22h12. Mon pipeline de génération bombarde Google avec une seule IPv4 publique. Résultat : 24 heures de blocage. Voici l'incident, le diagnostic et le garde-fou que j'ai mis en place pour qu'il ne se reproduise plus jamais.

Les meilleurs cours d'infrastructure ne sont pas dans les livres. Ils tombent à 22 h sur ton infra de production, sans prévenir, et te coûtent une nuit blanche. Ce qui suit est la transcription la plus fidèle possible d'un incident réel sur ORBITECH AI ACADEMY en avril 2026.

Contexte

ORBITECH génère en batch quotidien des milliers d'articles pédagogiques pour la base Alterra. Le pipeline tourne sur un VPS Contabo, fait du scraping de sources publiques (Wikipédia, Education.gouv.fr, sites de programmes officiels), enrichit le contenu via Claude, et stocke en Supabase.

Le VPS Contabo a une seule IPv4 publique, partagée par tous les processus sortants. Pas d'IPv6 active à cette époque. Le pipeline tourne en parallélisme contrôlé : ~12 workers, ~2 requêtes/seconde par worker.

L'incident

22 h 12. Démarrage du run quotidien. Comme d'habitude, le pipeline interroge Google Custom Search pour vérifier la disponibilité de certaines URL et rechercher des sources complémentaires.

22 h 47. Les workers commencent à recevoir des erreurs en cascade :

# Réponse type reçue après 35 minutes de run
HTTP 429 Too Many Requests
Server: gws (Google Web Server)

# Suivi de :
HTTP 403 Forbidden
X-Goog-Error: ip_blocked
Retry-After: 86400   # 24 heures

22 h 51. Diagnostic confirmé : Google a banni l'IPv4 publique du VPS pour 24 heures. Conséquences immédiates :

Leçon n° 1 : un service public (Google) peut te bannir unilatéralement sur n'importe quelle requête sortante. Tu n'as aucun recours immédiat à part attendre le délai indiqué dans Retry-After.

Pourquoi ?

Mes workers respectaient le quota officiel de Google Custom Search (100 req/jour gratuites, 10 000 req/jour payées). Mais en parallèle, le pipeline faisait aussi des requêtes HEAD directes vers google.com pour vérifier la disponibilité de pages — sans clé API. C'est ces requêtes-là, jamais comptabilisées dans mon esprit, qui ont déclenché le ban.

Du point de vue de Google, ces HEAD non-authentifiés ressemblent à du scraping. Avec ~24 workers tapant la même IP en parallèle, le seuil heuristique a sauté. Une seule IP, plusieurs centaines de requêtes par minute, ban.

La correction immédiate (court terme)

Pour reprendre le service avant le déban automatique, j'ai routé toutes les requêtes sortantes du pipeline via Cloudflare WARP (mode SOCKS5 sur le VPS). Cloudflare WARP utilise un pool d'adresses IPv6 — chaque connexion sort donc d'une IP différente.

# /etc/wireguard/wg0.conf — config WARP minimale
[Interface]
PrivateKey = ***
Address = 172.16.0.2/32
Address = 2606:4700:110:8d65::***/128
DNS = 1.1.1.1, 2606:4700:4700::1111
MTU = 1280

[Peer]
PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = engage.cloudflareclient.com:2408

Avec ce setup, le service est revenu en 5 minutes. Mais ce n'est pas une vraie solution : ça déplace simplement le problème vers les pools de Cloudflare, qui peuvent à leur tour être bannis sur certains services.

Le vrai fix (long terme) : fail-fast au démarrage

Le problème de fond, ce n'est pas le ban — c'est que j'ai démarré un pipeline de production avec une configuration réseau insuffisante sans le savoir. La solution, c'est de transformer cette configuration en précondition explicite vérifiée au démarrage. Pas démarrer si la précondition échoue.

// flood-master.js — garde-fou fail-fast
function assertNetworkConfig() {
  const ipv6Prefix = process.env.IPV6_PREFIX;

  if (!ipv6Prefix) {
    console.error("❌ IPV6_PREFIX non défini");
    console.error("   Le pipeline refuse de démarrer sans rotation IPv6.");
    console.error("   Cause: incident Google ban du 12 avril 2026.");
    console.error("   Fix: exporter IPV6_PREFIX=2a05:6e02::/32 puis relancer.");
    process.exit(1);
  }

  // Validation supplémentaire: vérifier que le prefix est routable
  if (!/^[0-9a-f:]+\/\d+$/.test(ipv6Prefix)) {
    console.error("❌ IPV6_PREFIX format invalide:", ipv6Prefix);
    process.exit(1);
  }

  console.log(`✅ IPv6 prefix actif: ${ipv6Prefix}`);
}

// Appelé AVANT toute initialisation du pipeline
assertNetworkConfig();

Trois éléments important dans ce code :

Leçon n° 2 : un garde-fou utile refuse de démarrer plutôt que de démarrer dans un état dégradé. Fail-fast > fail-silent à chaque fois qu'on a le choix.

Pourquoi IPv6 résout vraiment le problème

Avec un préfixe IPv6 routé (2a05:6e02::/32 dans mon cas, attribué par mon FAI), j'ai accès à 2^96 adresses publiques. Le pipeline peut faire tourner chaque requête sortante sur une IP différente.

Concrètement, ça veut dire qu'aucun service distant ne peut me bannir massivement, parce que mon trafic ressemble à 24 utilisateurs distincts avec 24 IPs différentes. Et ça veut dire qu'un script qui s'emballe et fait 10 000 requêtes en 5 minutes ne brûle pas l'IP de tout mon serveur.

Ce que j'ai changé dans toute mon infra après l'incident

Conclusion

Le ban Google de 24 heures m'a coûté une nuit. Le garde-fou fail-fast qu'il a engendré me protège pour les 10 prochaines années. Le ratio coût/bénéfice est en ma faveur — à condition de ne pas oublier la leçon.

Le hardening, ce n'est pas configurer le bon firewall avant qu'il ne se passe quelque chose. C'est capitaliser sur chaque incident en transformant la cause en précondition vérifiée. Tant que le code n'oublie pas, je peux oublier — c'est exactement ce que je veux d'une infrastructure.

Article précédent
Architecture d'un tuteur IA socratique
À lire aussi
LBO : le guide complet du Leveraged Buyout