IPv6 für Webentwickler
Was Webentwickler über IPv6 wissen müssen: URLs mit Klammern, Datenbankspeicherung, Socket-Programmierung und häufige zu vermeidende Fehler.
IPv6 für Webentwickler#
Falls Sie IPv6 ignoriert haben, weil „es ein Problem für später sein wird", später ist jetzt. Mobilfunknetze laufen IPv6-first. Einige Benutzer hinter NAT64 können Sie nur über IPv6 erreichen. Selbst localhost auf Ihrer Entwicklungsmaschine löst wahrscheinlich zu ::1 vor 127.0.0.1 auf.
Dieser Leitfaden behandelt, was Sie tatsächlich wissen müssen: IPv6 in URLs handhaben, Adressen in Datenbanken speichern, Socket-Programmierung und die Fehler, die Sie beißen werden, wenn Sie nicht vorsichtig sind.
TL;DR - Kurzübersicht
Wichtige Punkte:
- URLs benötigen eckige Klammern:
http://[2001:db8::1]:8080/ - Datenbanken: Verwenden Sie INET (PostgreSQL) oder VARCHAR(45) / VARBINARY(16) (MySQL)
- Sockets: Binden Sie an
::für Dual-Stack oder verwenden Sie getaddrinfo() für Client-Verbindungen - Häufige Fehler: Hardcodierte IPv4, fehlerhafte Regex-Validierung, zu kleine DB-Felder
Direkt zu: URLs | Datenbanken | Sockets | Häufige Bugs
IPv6 in URLs#
IPv6-Adressen enthalten Doppelpunkte, was mit dem Port-Separator in URLs kollidiert. Die Lösung ist eckige Klammernotation:
http://[2001:db8::1]:8080/api/users
https://[2606:2800:220:1:248:1893:25c8:1946]/Ohne Klammern können Parser nicht sagen, wo die Adresse endet und der Port beginnt. Dies gilt für:
- HTTP/HTTPS-URLs
- WebSocket-Verbindungen (
ws://[::1]:3000) - Datenbank-Connection-Strings
- Jedes URI-Schema
Beim programmatischen Generieren von URLs umschließen Sie IPv6-Adressen mit Klammern. Beim Parsen entfernen Sie sie vor Validierung oder Speicherung.
Datenbankspeicherung#
Der klassische Fehler ist VARCHAR(15) für IP-Adressen zu verwenden. Das passt für IPv4 (maximal 15 Zeichen: 255.255.255.255), aber nicht für IPv6.
PostgreSQL hat einen nativen INET-Typ, der sowohl IPv4 als auch IPv6 handhabt:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
ip_address INET NOT NULL
);
-- Automatische Validierung und Normalisierung
INSERT INTO users (ip_address) VALUES ('2001:db8::1');
INSERT INTO users (ip_address) VALUES ('192.0.2.1');Der INET-Typ speichert Adressen effizient, validiert sie beim Einfügen und unterstützt Netzwerkoperationen wie Subnetz-Matching mit <<- und >>-Operatoren.
MySQL fehlt ein nativer Typ, also verwenden Sie entweder:
VARBINARY(16)- speichert die binäre Darstellung (16 Bytes für IPv6, 4 für IPv4)VARCHAR(45)- speichert die String-Darstellung (maximale Länge von expandiertem IPv6)
Binäre Speicherung ist effizienter, erfordert aber Konvertierungsfunktionen:
-- Speichern
INSERT INTO users (ip_address) VALUES (INET6_ATON('2001:db8::1'));
-- Abrufen
SELECT INET6_NTOA(ip_address) FROM users;Normalisierung ist wichtig. IPv6-Adressen haben mehrere gültige Darstellungen:
2001:0db8:0000:0000:0000:0000:0000:00012001:db8::1(komprimiert)2001:db8:0:0:0:0:0:1(teilweise komprimiert)
Normalisieren Sie immer vor Vergleich oder Indizierung. Die meisten Bibliotheken haben eine kanonische Formfunktion.
Socket-Programmierung#
Die Socket-API behandelt IPv4 und IPv6 als separate Adressfamilien. Moderne Anwendungen sollten beide unterstützen.
Node.js verwendet standardmäßig Dual-Stack-Sockets:
const http = require('http');
// Bindet an :: (alle IPv6-Adressen) und akzeptiert IPv4 via Mapping
const server = http.createServer((req, res) => {
res.end(`Ihre IP: ${req.socket.remoteAddress}`);
});
server.listen(3000, '::');Die ::-Adresse ist das IPv6-Äquivalent zu 0.0.0.0 und akzeptiert Verbindungen auf allen Interfaces. Die meisten Systeme unterstützen IPv4-mapped IPv6-Adressen (::ffff:192.0.2.1), was einem einzelnen IPv6-Socket erlaubt, beide Protokolle zu handhaben.
Python erfordert explizite Dual-Stack-Handhabung:
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)Das IPV6_V6ONLY-Flag kontrolliert, ob der Socket nur IPv6 oder sowohl IPv4 als auch IPv6 akzeptiert.
Go macht Dual-Stack zum Standard:
listener, err := net.Listen("tcp", ":8080")
// Hört automatisch auf beiden IPv4 und IPv6Für Client-Verbindungen verwenden Sie immer getaddrinfo() (oder das Äquivalent Ihrer Sprache) anstatt Adressen manuell aufzulösen. Es handhabt IPv4, IPv6 und Dual-Stack-Szenarien korrekt:
import socket
# Nicht so
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('example.com', 80))
# So - funktioniert für beide IPv4 und 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])Lokales Testen#
Die meisten Systeme lösen localhost zu sowohl ::1 (IPv6) als auch 127.0.0.1 (IPv4) auf. Prüfen Sie Ihre /etc/hosts:
127.0.0.1 localhost
::1 localhostFalls Ihre Anwendung nur an 127.0.0.1 bindet, akzeptiert sie keine IPv6-Verbindungen. Binden Sie an :: für Dual-Stack oder explizit an beide Adressen.
Um IPv6-only-Verhalten zu testen, deaktivieren Sie IPv4 auf Ihrem Loopback-Interface oder verwenden Sie [::1] explizit in Ihrem HTTP-Client:
curl http://[::1]:3000/Für realistisches Testen verwenden Sie ein IPv6-only-Testnetzwerk. Viele Cloud-Anbieter bieten IPv6-only-Instanzen, die Sie zwingen, Randfälle wie NAT64/DNS64 zu handhaben.
CDN und Origin-Server#
Die meisten CDNs (Cloudflare, Fastly, AWS CloudFront) unterstützen IPv6 standardmäßig. Sie bedienen Inhalte über IPv6 an Clients und übersetzen bei Bedarf zu IPv4 für Ihren Origin.
Der Haken: Falls Sie APIs direkt exponieren (CDN umgehend), muss Ihr Origin-Server IPv6 unterstützen. Prüfen Sie, dass Ihr DNS AAAA-Records hat und Ihre Firewall IPv6-Verkehr erlaubt.
Häufige Fehler#
Regex-Validierung. IPv6-Regex-Muster sind notorisch komplex und normalerweise falsch:
// Nicht so
const ipv6Regex = /^([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}$/i;
// Schlägt bei ::-Kompression, IPv4-mapped Adressen, Zone IDs fehl...Verwenden Sie stattdessen eine ordentliche Parsing-Bibliothek. Jede große Sprache hat eine, die IPv6 korrekt handhabt. Für Validierung verwenden Sie unser IPv6 Validator-Tool.
Fest codierte IPv4-Adressen. Durchsuchen Sie Ihre Codebasis nach Mustern wie:
const API_SERVER = 'http://192.168.1.100:3000'; // Funktioniert nicht mit IPv6Verwenden Sie stattdessen Hostnamen oder unterstützen Sie beide Adressfamilien.
IP-basiertes Rate-Limiting. IPv6-Adressen ändern sich häufig aufgrund von Privacy Extensions. Rate-Limiting nach exakter Adresse wird fehlschlagen. Limitieren Sie stattdessen nach /64-Subnetz:
// Schlecht
const key = `rate:${ipAddress}`;
// Besser für IPv6
const key = `rate:${ipv6ToSubnet64(ipAddress)}`;Bibliotheken ohne IPv6-Unterstützung. Ältere HTTP-Clients, Datenbanktreiber und Netzwerkbibliotheken handhaben möglicherweise IPv6 nicht. Testen Sie mit tatsächlichen IPv6-Adressen, nicht nur localhost. Falls eine Bibliothek fehlschlägt, prüfen Sie auf Updates oder Alternativen.
URL-Parsing-Randfälle. Stellen Sie sicher, dass Ihr Router/Framework geklammerte IPv6-Adressen handhabt:
GET http://[2001:db8::1]:8080/api/users
Host: [2001:db8::1]:8080Einige Parser beinhalten fälschlicherweise die Klammern im Host-Header oder extrahieren die Adresse nicht korrekt.
Checkliste#
Ihre Anwendung ist IPv6-bereit, wenn:
- Datenbankspalten können 45-Zeichen-Strings speichern oder native IP-Typen verwenden
- Server binden an
::oder hören explizit auf beiden IPv4 und IPv6 - Client-Code verwendet
getaddrinfo()oder Äquivalent für Namensauflösung - IP-Validierung verlässt sich nicht auf Regex
- Keine fest codierten IPv4-Adressen in Konfiguration
- Rate-Limiting und Geolocation handhaben IPv6-Subnetze
- URL-Parsing handhabt geklammerte Notation
IPv6 ist nicht mehr optional. Bauen Sie es von Anfang an ein, und Sie vermeiden die schmerzhafte Migration später.
Verwandte Artikel#
- IPv6-Grundlagen - Verstehen Sie IPv6-Adressierung und Kernkonzepte
- IPv6-Adresstypen - Lernen Sie die verschiedenen Typen von IPv6-Adressen kennen, die Ihr Code antreffen wird
Validieren Sie IPv6-Adressen
Verwenden Sie unseren IPv6 Validator und Ping-Tool, um die IPv6-Unterstützung Ihrer Anwendung zu testen.