عند إضافة بادئة IPv6 إلى نفق بين موقعين، لا تسلك الحزمة الطريق الذي يوحي به المخطط۔ تأخذ البوابة المحلية حزمة IPv6 كاملة، وتشفّرها، وتضع أمامها ترويسة IP خارجية يحددها عنوانا الطرفين، لا ما في الداخل۔ تنزع البوابة البعيدة تلك الترويسة الخارجية وتمرّر الحزمة الأصلية إلى شبكتها المحلية، حيث تعود حزمة IPv6 عادية۔ النفق الخارجي والحركة الداخلية محادثتان منفصلتان تشتركان في مفتاح وزوج أطراف ولا شيء آخر۔

ترويسة اثنتان، عائلتا عناوين

في وضع نفق IPsec تصبح حزمة IPv6 الداخلية هي الحمولة خلف ترويسة ESP۔ الترويسة الخارجية التي تحمل حزمة ESP هذه قد تكون IPv4 أو IPv6، وهي تتبع local_addrs وremote_addrs۔ WireGuard يفعل الأمر نفسه بمراسم أقل: الحزمة الداخلية هي حمولة مخطط UDP إلى الطرف المقابل۔ كلتاهما تتركان الترويسة الداخلية سليمة، ولهذا يمكن للجهة البعيدة توجيهها بعد إزالة التغليف۔

لا يرى المسار بين الموقعين إلا UDP 4500 عندما يستخدم IPsec اجتياز NAT، أو UDP 51820 لمستمع WireGuard الافتراضي۔ يمكن أن يكون أي موجه على المسار IPv4 فقط وحركة IPv6 تعبر مع ذلك، لأنها لا تظهر أبدًا كحزمة IPv6 على ذلك المسار۔ يمنح ذلك فصلًا أوليًا نظيفًا: tcpdump -ni eth0 udp port 51820 يُظهر المسار المشفّر، tcpdump -ni wg0 ip6 يُظهر الحركة الداخلية۔ وجود التقاط خارجي مزدحم مع آخر داخلي صامت يعني أن النواة لا تضع IPv6 في النفق؛ فذلك توجيه أو سياسة، لا حالة وصلة۔

تُنقص البوابة أيضًا حد القفزات الداخلي عند التمرير، لذا تُعدّ الأطراف موجهات على مسار IPv6۔ يتحرك عدد القفزات الخارجي وحد القفزات الداخلي باستقلال، والحزمة التي تموت عند البوابة البعيدة ماتت في التمرير لا في التشفير۔

المحددات وAllowedIPs هما قائمة الأذونات

يتفاوض IKEv2 على أي بادئات داخلية يمكن لـ child SA أن تحملها۔ على strongSwan 5.9 وأحدث يبدو كتابتها في swanctl.conf هكذا:

children {
  net6 {
    local_ts  = 2001:db8:aa::/48
    remote_ts = 2001:db8:bb::/48
    mode = tunnel
    esp_proposals = aes256gcm16-prfsha384-ecp384
    start_action = trap
  }
}

إن حذفت local_ts وremote_ts فسيستنتجهما strongSwan من الشبكات الفرعية للواجهة التي يختارها۔ على مضيف ثنائي المكدس غالبًا ما ينتج ذلك الاختصار زوجًا من IPv4 فقط: يرتفع SA ويُرفض IPv6 قبل أن يصل إلى شيفرة ESP۔ كتابة البادئتين تجعل SA أهلًا لحملها، وstart_action = trap يرفعه عند أول حزمة مطابقة۔

لدى WireGuard قائمة واحدة تؤدي وظيفتين۔ في كتلة القرين، AllowedIPs = 2001:db8:bb::/48, fd00:bb::/48 هو المسار المثبت عند الإرسال والمرشح المطبق عند الاستقبال معًا: الحزمة المفككة التي يقع مصدرها الداخلي خارج قائمة ذلك القرين تُهمل بصمت۔ يضيف wg-quick مسارًا لكل مدخل، لذا لا تحتاج كتلة القرين أدناه إلى أمر ip -6 route منفصل۔

[Interface]
Address = 2001:db8:aa:ff::1/64, fd00:aa:ff::1/64
ListenPort = 51820

[Peer]
PublicKey = <site-b-public-key>
Endpoint = 203.0.113.20:51820
AllowedIPs = 2001:db8:bb::/48, fd00:bb::/48

يجب أن تكون القائمتان متطابقتين: يقبل الموقع B بادئة الموقع A كمحدد بعيد ويوجهها عائدة، ولا يعمل النفق إلا إذا توافق الاتجاهان۔ القائمة غير المتماثلة تعطي العرَض الذي يستهلك أكبر وقت — مصافحة سليمة، وعدادات تتحرك على جانب واحد، و اختبار ping من A إلى B ينجح بينما لا شيء من B يصل إلى A۔

التمرير والمسارات وبادئة العودة

لا تمرّر لينكس IPv6 حتى تقول ذلك، والإعداد يكون لكل مساحة أسماء لا لكل واجهة:

sysctl -w net.ipv6.conf.all.forwarding=1
ip -6 route add 2001:db8:bb::/48 dev wg0
ip -6 route get 2001:db8:bb::10 from 2001:db8:aa::10

السطر الثاني هو ما ينساه الناس في التصاميم القائمة على المسارات۔ يثبت IPsec القائم على السياسة سياسة XFRM تطابق البادئات، لكن إعدادًا قائمًا على المسارات مع vti6 أو WireGuard يحتاج إلى مسار IPv6 حقيقي يشير إلى ذلك الجهاز۔ احفظ sysctl تحت /etc/sysctl.d/؛ وإلا أعادت إعادة التشغيل التمرير إلى الإطفاء بصمت۔

للتمرير أثر جانبي يجدر معرفته: تتجاهل النواة حينها إعلانات الموجهات إلا إذا كان net.ipv6.conf.<wan>.accept_ra يساوي 2، لذا قد تفقد بوابة يصل عنوان WAN الخاص بها عبر SLAAC مسارها الافتراضي لحظة تفعيل التمرير۔ اضبط accept_ra = 2 على تلك الواجهة في الملف نفسه فيبقى المسار۔ وعلى نواة الموقع B أيضًا أن تتعلم 2001:db8:aa::/48 من بوابة النفق، عبر مسار ثابت أو بروتوكول توجيه فوق النفق، وإلا مات الرد داخل شبكة B نفسها۔

فحص بأربع خطوات يحدد موقع الانقطاع

اعمل بهذا الترتيب وتوقف عند أول خطوة تفشل، لأن كل خطوة لاحقة تعتمد على ما قبلها۔

  1. المحددات: ينبغي أن يُظهر swanctl --list-sas زوج بادئات IPv6 على child SA، أو wg show wg0 allowed-ips البادئة البعيدة مع latest-handshakes حديث۔
  2. مسار النواة: يجب أن يجيب ip -6 route get 2001:db8:bb::10 بجهاز النفق، لا بواجهة WAN۔
  3. التقاط داخلي: tcpdump -ni wg0 ip6 أثناء اختبار ping بين مضيفي LAN حقيقيين۔ الحزم التي تخرج دون أي حزمة تعود تشير إلى مسار B أو جدار حمايته؛ وانعدام الحزم كليًا يشير رجوعًا إلى الخطوة 1 أو 2۔
  4. الوجهة: على مضيف B يؤكد ss -6 -ltn أن الخدمة تستمع على IPv6، وتبيّن عدادات جدار الحماية المحلي هل قُبلت الحزمة أم أُسقطت۔

الـ MTU يدخل في المسار نفسه۔ لا تجزّئ موجهات IPv6، لذا تُسقط الحزمة الأكبر من اللازم ويعود Packet Too Big إلى المرسل۔ إن نجحت المصافحات واختبارات ping الصغيرة لكن نقل ملف توقف، فقلّل الحمولة حتى تعبر: ping -6 -s 1400 -c 3 2001:db8:bb::10۔ وواجهات WireGuard لها افتراضيًا MTU بمقدار 1420 بايت، وIPsec فوق IPv4 يخصم أكثر، لذا ضبط MTU الداخلي أفضل من الأمل في اكتشاف MTU المسار عبر جدار حماية يُسقط ICMPv6۔

أنماط فشل تبدو كمشكلات جدار حماية

الأكثر شيوعًا ليس جدار حماية إطلاقًا: ترتبط الخدمة بـ 0.0.0.0 بدل ::، وسجل AAAA موجود، ويحصل العميل على رفض سريع عبر IPv6 يخفيه متصفح ثنائي المكدس بالرجوع إلى IPv4۔ إن فشلت بعض التطبيقات فقط، فافحص عائلة الاستماع قبل لمس مجموعة قواعد۔

الثاني هو ترشيح ICMPv6۔ إن Neighbor Discovery وPacket Too Big جزء من التشغيل العادي لا من التشخيص، وسياسة تُسقط كل ICMPv6 تنتج نفقًا يتصل ويتحقق ثم يتوقف عند كل ما هو أكبر من حزمة صغيرة۔ اسمح بالأنواع التي يعتمد عليها المسار واترك العدادات مفتوحة كي يكون الإسقاط مرئيًا۔

الثالث بادئة تُضاف إلى النفق ولا تُضاف قط إلى مخطط عناوين الموقع الذي يملكها، فلا يعلنها أي موجه ولا يستطيع أي مضيف الرد منها۔ ابدأ ببادئة واحدة وزوج مضيفين واحد، وأثبت الاتجاهين بالخطوات الأربع، ثم أضف الباقي؛ فالبادئة المعطوبة تبقى سطرًا واحدًا في إعداد بدل إعادة تصميم۔ والمرجع الرسمي الوحيد الذي يستحق الإبقاء عليه مفتوحًا هو RFC 8200، الذي يعرّف الترويسة التي يحملها النفق۔

مقالات ذات صلة