IPv6 لمطوري الويب
ما يحتاج مطورو الويب معرفته عن IPv6: URLs مع أقواس، تخزين قواعد البيانات، برمجة المقابس، والأخطاء الشائعة لتجنبها.
إذا كنت تتجاهل IPv6 لأن «ستكون مشكلة لاحقاً»، لاحقاً الآن. تشغل الشبكات المحمولة IPv6 أولاً. بعض المستخدمين وراء NAT64 يمكنهم الوصول إليك فقط عبر IPv6. حتى localhost على جهاز التطوير الخاص بك من المحتمل أن يحل إلى ::1 قبل 127.0.0.1.
يغطي هذا الدليل ما تحتاج معرفته فعلاً: التعامل مع IPv6 في URLs، تخزين العناوين في قواعد البيانات، برمجة المقابس، والأخطاء التي ستعضّك إذا لم تكن حذراً.
TL;DR - ملخص سريع
النقاط الرئيسية:
- استخدم أقواس مربعة في URLs:
http://[2001:db8::1]:8080/api - تخزين قاعدة البيانات: استخدم INET/VARBINARY، وليس VARCHAR - يتطلب IPv6 حتى 45 حرفاً
- برمجة المقابس: استخدم
AF_INET6، تعامل مع العناوين كثنائي، اختبر مع::1 - تجنب التعبيرات النمطية لـ IPv4 فقط، تحقق من صحة كلا تنسيقي العناوين
- الاستماع المزدوج المكدس: ربط
::يقبل IPv4 (عبر IPv4-mapped) و IPv6
انتقل إلى: URLs | قواعد البيانات | المقابس | الأخطاء الشائعة
IPv6 في URLs#
تحتوي عناوين IPv6 على نقطتين رأسيتين، مما يتعارض مع فاصل المنفذ في URLs. الحل هو ترميز الأقواس المربعة:
http://[2001:db8::1]:8080/api/users
https://[2606:2800:220:1:248:1893:25c8:1946]/بدون أقواس، لا يمكن للمحللات معرفة أين ينتهي العنوان وأين يبدأ المنفذ. هذا ينطبق على:
- URLs HTTP/HTTPS
- اتصالات WebSocket (
ws://[::1]:3000) - سلاسل اتصال قاعدة البيانات
- أي مخطط URI
عند توليد URLs برمجياً، لف عناوين IPv6 في أقواس. عند التحليل، انزعها قبل التحقق أو التخزين.
تخزين قاعدة البيانات#
الخطأ الكلاسيكي هو استخدام VARCHAR(15) لعناوين IP. ذلك يناسب IPv4 (الحد الأقصى 15 حرفاً: 255.255.255.255) لكن ليس IPv6.
PostgreSQL لديه نوع INET أصلي يتعامل مع كل من IPv4 وIPv6:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
ip_address INET NOT NULL
);
-- التحقق والتطبيع التلقائي
INSERT INTO users (ip_address) VALUES ('2001:db8::1');
INSERT INTO users (ip_address) VALUES ('192.0.2.1');يخزن نوع INET العناوين بكفاءة، يتحقق منها عند الإدخال، ويدعم عمليات الشبكة مثل مطابقة الشبكة الفرعية مع مشغلي << و>>.
MySQL يفتقر لنوع أصلي، لذا استخدم إما:
VARBINARY(16)- تخزين التمثيل الثنائي (16 بايت لـ IPv6، 4 لـ IPv4)VARCHAR(45)- تخزين التمثيل النصي (الطول الأقصى لـ IPv6 الموسعة)
التخزين الثنائي أكثر كفاءة لكن يتطلب دوال تحويل:
-- تخزين
INSERT INTO users (ip_address) VALUES (INET6_ATON('2001:db8::1'));
-- استرجاع
SELECT INET6_NTOA(ip_address) FROM users;التطبيع مهم. لعناوين IPv6 تمثيلات صالحة متعددة:
2001:0db8:0000:0000:0000:0000:0000:00012001:db8::1(مضغوط)2001:db8:0:0:0:0:0:1(مضغوط جزئياً)
طبّع دائماً قبل المقارنة أو الفهرسة. معظم المكتبات لديها دالة للصيغة القانونية.
برمجة المقابس#
تعامل واجهة برمجة التطبيقات للمقبس IPv4 وIPv6 كعائلات عناوين منفصلة. يجب على التطبيقات الحديثة دعم كليهما.
Node.js افتراضياً لمقابس مزدوجة المكدس:
const http = require('http');
// يربط بـ :: (جميع عناوين IPv6) ويقبل IPv4 عبر التعيين
const server = http.createServer((req, res) => {
res.end(`Your IP: ${req.socket.remoteAddress}`);
});
server.listen(3000, '::');عنوان :: هو مكافئ IPv6 لـ 0.0.0.0، قبول الاتصالات على جميع الواجهات. معظم الأنظمة تدعم عناوين IPv6 المعينة لـ IPv4 (::ffff:192.0.2.1)، مما يسمح لمقبس IPv6 واحد بالتعامل مع كلا البروتوكولين.
Python يتطلب تعاملاً صريحاً للمكدس المزدوج:
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)يتحكم علم IPV6_V6ONLY فيما إذا كان المقبس يقبل IPv6 فقط أو كلاً من IPv4 وIPv6.
Go يجعل المكدس المزدوج افتراضياً:
listener, err := net.Listen("tcp", ":8080")
// يستمع تلقائياً على كل من IPv4 وIPv6لاتصالات العميل، استخدم دائماً getaddrinfo() (أو ما يكافئه في لغتك) بدلاً من حل العناوين يدوياً. يتعامل مع IPv4 وIPv6 وسيناريوهات المكدس المزدوج بشكل صحيح:
import socket
# لا تفعل هذا
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('example.com', 80))
# افعل هذا - يعمل لكل من IPv4 و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])الاختبار المحلي#
تحل معظم الأنظمة localhost إلى كل من ::1 (IPv6) و127.0.0.1 (IPv4). تحقق من /etc/hosts الخاص بك:
127.0.0.1 localhost
::1 localhostإذا كان تطبيقك يربط فقط بـ 127.0.0.1، لن يقبل اتصالات IPv6. اربط بـ :: للمكدس المزدوج أو اربط صراحةً بكلا العنوانين.
لاختبار سلوك IPv6 فقط، عطّل IPv4 على واجهة الارتداد الخاصة بك أو استخدم [::1] صراحةً في عميل HTTP الخاص بك:
curl http://[::1]:3000/للاختبار الواقعي، استخدم شبكة اختبار IPv6 فقط. يقدم العديد من مزودي السحابة مثيلات IPv6 فقط تجبرك على التعامل مع حالات الحافة مثل NAT64/DNS64.
CDN وخوادم المنشأ#
معظم CDNs (Cloudflare، Fastly، AWS CloudFront) تدعم IPv6 افتراضياً. سيخدمون المحتوى عبر IPv6 للعملاء ويترجمون إلى IPv4 لمنشأك إذا لزم الأمر.
المحاصرة: إذا كشفت APIs مباشرةً (متجاوزاً CDN)، يجب أن يدعم خادم المنشأ الخاص بك IPv6. تحقق من أن DNS الخاص بك لديه سجلات AAAA وأن جدار الحماية الخاص بك يسمح بحركة مرور IPv6.
الأخطاء الشائعة#
التحقق من regex. أنماط regex لـ IPv6 معقدة بشكل سيئ السمعة وعادةً خاطئة:
// لا تفعل هذا
const ipv6Regex = /^([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}$/i;
// يفشل على ضغط ::، العناوين المعينة لـ IPv4، معرفات المنطقة...استخدم مكتبة تحليل مناسبة بدلاً من ذلك. كل لغة رئيسية لديها واحدة تتعامل مع IPv6 بشكل صحيح. للتحقق، استخدم أداة مدقق IPv6.
عناوين IPv4 مشفرة. ابحث في قاعدة الكود الخاصة بك عن أنماط مثل:
const API_SERVER = 'http://192.168.1.100:3000'; // لن يعمل مع IPv6استخدم أسماء المضيفات بدلاً من ذلك، أو ادعم كلا عائلتي العناوين.
تحديد المعدل بناءً على IP. تتغير عناوين IPv6 بشكل متكرر بسبب امتدادات الخصوصية. تحديد المعدل بالعنوان الدقيق سيفشل. حدد بواسطة شبكة فرعية /64 بدلاً من ذلك:
// سيء
const key = `rate:${ipAddress}`;
// أفضل لـ IPv6
const key = `rate:${ipv6ToSubnet64(ipAddress)}`;مكتبات بدون دعم IPv6. قد لا تتعامل عملاء HTTP الأقدم وبرامج تشغيل قواعد البيانات ومكتبات الشبكات مع IPv6. اختبر مع عناوين IPv6 فعلية، وليس فقط localhost. إذا فشلت مكتبة، تحقق من التحديثات أو البدائل.
حالات حافة تحليل URL. تأكد من أن موجهك/إطارك يتعامل مع عناوين IPv6 المقوسة:
GET http://[2001:db8::1]:8080/api/users
Host: [2001:db8::1]:8080بعض المحللات يتضمنون الأقواس بشكل غير صحيح في رأس Host أو يفشلون في استخراج العنوان بشكل صحيح.
قائمة تحقق#
تطبيقك جاهز لـ IPv6 عندما:
- يمكن لأعمدة قاعدة البيانات تخزين سلاسل 45 حرفاً أو استخدام أنواع IP أصلية
- تربط الخوادم بـ
::أو تستمع صراحةً على كل من IPv4 وIPv6 - يستخدم كود العميل
getaddrinfo()أو ما يكافئه لحل الأسماء - لا يعتمد التحقق من IP على regex
- لا توجد عناوين IPv4 مشفرة في التكوين
- يتعامل تحديد المعدل وتحديد الموقع الجغرافي مع شبكات IPv6 الفرعية
- يتعامل تحليل URL مع الترميز المقوس
IPv6 ليس اختيارياً بعد الآن. ابنِه من البداية، وستتجنب الترحيل المؤلم لاحقاً.
مقالات ذات صلة#
- أساسيات IPv6 - فهم عناوين IPv6 والمفاهيم الأساسية
- أنواع عناوين IPv6 - تعلم الأنواع المختلفة من عناوين IPv6 التي سيواجهها كودك