ping6.net
Meilleures Pratiques

IPv6 pour les développeurs web

Ce que les développeurs web doivent savoir sur IPv6 : URLs avec crochets, stockage en base de données, programmation socket et bugs courants à éviter.

ping6.net14 décembre 20247 min read
IPv6développement webprogrammationbases de donnéessockets

Si vous avez ignoré IPv6 parce que « ce sera un problème pour plus tard », plus tard c'est maintenant. Les réseaux mobiles fonctionnent en IPv6-first. Certains utilisateurs derrière NAT64 ne peuvent vous atteindre que via IPv6. Même localhost sur votre machine de développement résout probablement vers ::1 avant 127.0.0.1.

Ce guide couvre ce que vous devez réellement savoir : gérer IPv6 dans les URLs, stocker les adresses en base de données, programmation socket, et les bugs qui vous mordront si vous n'êtes pas prudent.

TL;DR - Résumé rapide

Points clés :

  • URLs IPv6 nécessitent des crochets : http://[2001:db8::1]:8080/
  • Stockez les adresses comme chaînes (VARCHAR 45) ou utilisez des types natifs (PostgreSQL INET)
  • Les sockets écoutent sur :: pour dual-stack (IPv4 et IPv6)
  • Validez avec des regex ou des bibliothèques — n'analysez pas manuellement

Aller à : URLs | Base de données | Sockets | Bibliothèques

IPv6 dans les URLs#

Les adresses IPv6 contiennent des deux-points, ce qui entre en conflit avec le séparateur de port dans les URLs. La solution est la notation entre crochets :

http://[2001:db8::1]:8080/api/users
https://[2606:2800:220:1:248:1893:25c8:1946]/

Sans crochets, les parseurs ne peuvent pas dire où l'adresse se termine et où le port commence. Ceci s'applique à :

  • URLs HTTP/HTTPS
  • Connexions WebSocket (ws://[::1]:3000)
  • Chaînes de connexion base de données
  • N'importe quel schéma URI

Quand vous générez des URLs par programme, enveloppez les adresses IPv6 dans des crochets. Quand vous analysez, supprimez-les avant validation ou stockage.

Stockage en base de données#

L'erreur classique est d'utiliser VARCHAR(15) pour les adresses IP. Cela convient à IPv4 (maximum 15 caractères : 255.255.255.255) mais pas IPv6.

PostgreSQL a un type natif INET qui gère IPv4 et IPv6 :

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  ip_address INET NOT NULL
);
 
-- Validation et normalisation automatiques
INSERT INTO users (ip_address) VALUES ('2001:db8::1');
INSERT INTO users (ip_address) VALUES ('192.0.2.1');

Le type INET stocke les adresses efficacement, les valide à l'insertion et supporte les opérations réseau comme la correspondance de sous-réseau avec les opérateurs << et >>.

MySQL manque de type natif, donc utilisez soit :

  • VARBINARY(16) - stocker la représentation binaire (16 octets pour IPv6, 4 pour IPv4)
  • VARCHAR(45) - stocker la représentation chaîne (longueur max d'IPv6 étendu)

Le stockage binaire est plus efficace mais nécessite des fonctions de conversion :

-- Stocker
INSERT INTO users (ip_address) VALUES (INET6_ATON('2001:db8::1'));
 
-- Récupérer
SELECT INET6_NTOA(ip_address) FROM users;

La normalisation compte. Les adresses IPv6 ont plusieurs représentations valides :

  • 2001:0db8:0000:0000:0000:0000:0000:0001
  • 2001:db8::1 (compressée)
  • 2001:db8:0:0:0:0:0:1 (partiellement compressée)

Normalisez toujours avant de comparer ou indexer. La plupart des bibliothèques ont une fonction de forme canonique.

Programmation socket#

L'API socket traite IPv4 et IPv6 comme des familles d'adresses séparées. Les applications modernes devraient supporter les deux.

Node.js met par défaut sur des sockets dual-stack :

const http = require('http');
 
// Se lie à :: (toutes adresses IPv6) et accepte IPv4 via mapping
const server = http.createServer((req, res) => {
  res.end(`Your IP: ${req.socket.remoteAddress}`);
});
 
server.listen(3000, '::');

L'adresse :: est l'équivalent IPv6 de 0.0.0.0, acceptant les connexions sur toutes les interfaces. La plupart des systèmes supportent les adresses IPv4 mappées IPv6 (::ffff:192.0.2.1), permettant à un seul socket IPv6 de gérer les deux protocoles.

Python nécessite une gestion dual-stack explicite :

import socket
 
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
sock.bind(('::', 8080))
sock.listen(5)

Le drapeau IPV6_V6ONLY contrôle si le socket n'accepte qu'IPv6 ou IPv4 et IPv6.

Go fait de dual-stack le défaut :

listener, err := net.Listen("tcp", ":8080")
// Écoute automatiquement sur IPv4 et IPv6

Pour les connexions client, utilisez toujours getaddrinfo() (ou l'équivalent de votre langage) au lieu de résoudre manuellement les adresses. Cela gère correctement IPv4, IPv6 et les scénarios dual-stack :

import socket
 
# Ne faites pas ceci
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('example.com', 80))
 
# Faites ceci - fonctionne pour IPv4 et IPv6
addr_info = socket.getaddrinfo('example.com', 80, socket.AF_UNSPEC, socket.SOCK_STREAM)
sock = socket.socket(addr_info[0][0], addr_info[0][1])
sock.connect(addr_info[0][4])

Tests locaux#

La plupart des systèmes résolvent localhost vers ::1 (IPv6) et 127.0.0.1 (IPv4). Vérifiez votre /etc/hosts :

127.0.0.1       localhost
::1             localhost

Si votre application se lie uniquement à 127.0.0.1, elle n'acceptera pas les connexions IPv6. Liez-vous à :: pour dual-stack ou liez-vous explicitement aux deux adresses.

Pour tester le comportement IPv6-only, désactivez IPv4 sur votre interface loopback ou utilisez [::1] explicitement dans votre client HTTP :

curl http://[::1]:3000/

Pour des tests réalistes, utilisez un réseau test IPv6-only. Beaucoup de fournisseurs cloud offrent des instances IPv6-only qui vous forcent à gérer les cas limites comme NAT64/DNS64.

CDN et serveurs d'origine#

La plupart des CDN (Cloudflare, Fastly, AWS CloudFront) supportent IPv6 par défaut. Ils serviront le contenu en IPv6 aux clients et traduiront vers IPv4 pour votre origine si nécessaire.

Le piège : si vous exposez des API directement (en contournant le CDN), votre serveur d'origine doit supporter IPv6. Vérifiez que votre DNS a des enregistrements AAAA et que votre pare-feu autorise le trafic IPv6.

Bugs courants#

Validation regex. Les motifs regex IPv6 sont notoirement complexes et généralement faux :

// Ne faites pas ceci
const ipv6Regex = /^([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}$/i;
// Échoue sur compression ::, adresses IPv4 mappées, ID de zone...

Utilisez plutôt une bibliothèque d'analyse appropriée. Chaque langage majeur en a une qui gère correctement IPv6. Pour la validation, utilisez notre outil Validateur IPv6.

Adresses IPv4 codées en dur. Recherchez dans votre code des motifs comme :

const API_SERVER = 'http://192.168.1.100:3000';  // Ne fonctionnera pas avec IPv6

Utilisez des noms d'hôte à la place, ou supportez les deux familles d'adresses.

Limitation de taux basée IP. Les adresses IPv6 changent fréquemment à cause des extensions de confidentialité. La limitation de taux par adresse exacte échouera. Limitez par sous-réseau /64 à la place :

// Mauvais
const key = `rate:${ipAddress}`;
 
// Meilleur pour IPv6
const key = `rate:${ipv6ToSubnet64(ipAddress)}`;

Bibliothèques sans support IPv6. Les clients HTTP plus anciens, pilotes de base de données et bibliothèques réseau peuvent ne pas gérer IPv6. Testez avec de vraies adresses IPv6, pas juste localhost. Si une bibliothèque échoue, cherchez des mises à jour ou alternatives.

Cas limites d'analyse d'URL. Assurez-vous que votre routeur/framework gère les adresses IPv6 entre crochets :

GET http://[2001:db8::1]:8080/api/users
Host: [2001:db8::1]:8080

Certains parseurs incluent incorrectement les crochets dans l'en-tête Host ou échouent à extraire correctement l'adresse.

Liste de vérification#

Votre application est prête pour IPv6 quand :

  • Les colonnes de base de données peuvent stocker des chaînes de 45 caractères ou utilisent des types IP natifs
  • Les serveurs se lient à :: ou écoutent explicitement sur IPv4 et IPv6
  • Le code client utilise getaddrinfo() ou équivalent pour la résolution de noms
  • La validation IP ne dépend pas de regex
  • Pas d'adresses IPv4 codées en dur dans la configuration
  • La limitation de taux et géolocalisation gèrent les sous-réseaux IPv6
  • L'analyse d'URL gère la notation entre crochets

IPv6 n'est plus optionnel. Intégrez-le dès le départ, et vous éviterez la migration douloureuse plus tard.

Articles connexes#

Validez les adresses IPv6

Utilisez notre Validateur IPv6 et Outil Ping pour tester le support IPv6 de votre application.