يعرض متصفحك على المضيف عنوان خروج VPN، بينما تُبلغ الحاوية عن اتصالك المنزلي، فيسمي أحدهم ذلك تسريبًا. لم يتسرب شيء. نفق المضيف عبارة عن مجموعة من الواجهات والمسارات والقواعد التي تنتمي إلى نطاق أسماء شبكة المضيف، أما الحاوية على جسر فهي نطاق أسماء مختلف له مساره الافتراضي الخاص. لقد جلست على حزمة Compose كان فيها عميل VPN متصلًا لأسابيع ولم تدخل فيها حزمة واحدة من الحاوية.

افحص نطاق الأسماء قبل أيقونة الشريط

نطاقات الأسماء هي جوهر المسألة. عندما يشغّل Docker حاوية على شبكة جسر، فإنه ينشئ نطاق أسماء شبكيًا، ويصل أحد طرفي زوج veth بداخله، ويمنح ذلك النطاق عنوانًا ومسارًا افتراضيًا. أما واجهة النفق، أيًا كان اسمها، فتعيش في نطاق أسماء المضيف. لا يمكن للحركة داخل الحاوية رؤيتها، ولا يغيّر أي إعداد في العميل ذلك من الخارج.

هناك حركتان مدعومتان تُخرجانك من العزلة. --network host يضع الحاوية داخل نطاق أسماء المضيف، فترث مسارات المضيف وبالتالي النفق. و--network container:vpn يشارك نطاق أسماء حاوية أخرى، وهكذا ترسل معظم تصاميم الحاوية الجانبية حمل العمل عبر حاوية VPN. كلاهما خيار صريح؛ وعادةً يكون واحد فقط منهما هو ما قصده من يقوم بالنشر.

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

تتبّع الحزمة عند خروجها من الجسر

ترسل حاوية الجسر حزمتها إلى بوابتها الافتراضية، وهي واجهة الجسر على المضيف. ثم يمرّر المضيف الحزمة، وفي الإعداد الافتراضي، يترجم عنوان المصدر إلى عنوانه قبل أن تغادر الحزمة. خطوة الترجمة هذه هي ما يُبطل السياسة بهدوء.

بحلول الوقت الذي تصل فيه الحزمة إلى نقطة نهاية النفق، فإنها تحمل عنوان المضيف. وأي قاعدة أو مسار سياسة أو قرار نفق منقسم يعتمد على العنوان الأصلي للحاوية يتوقف عن المطابقة، ولا يمكن التمييز بين حاويتين مخصصتين للخروج عبر مخرجين مختلفين بالاعتماد على المصدر وحده. إذا كنت بحاجة إلى توجيه لكل حاوية، فيجب أن يحدث القرار قبل الترجمة أو داخل نطاق أسماء تتحكم به.

يدير Docker هذه القواعد بنفسه، عبر أي واجهة خلفية لجدار الحماية ضُبط بها البرنامج الخفي. القواعد المكتوبة يدويًا خارج الخطاف المدعوم لحركة المرور المُمرَّرة، DOCKER-USER، يمكن إعادة ترتيبها أو إسقاطها عند إعادة تشغيل البرنامج الخفي أو ترقية المضيف. إن توثيق Docker لتصفية الحزم يعرض ترتيب السلاسل؛ والنقطة العملية هي أن كل قاعدة تحتاج إلى مالك وإلى مسار إعادة تحميل اختبرته فعليًا.

اختبر النظامين بشكل منفصل

الأدلة من نطاق أسماء واحد لا تقول شيئًا عن الآخر. الطلب الذي يُنفَّذ داخل حاوية VPN يثبت أن النفق يعمل لتلك الحاوية. وهو ليس دليلًا على المضيف، والأمر نفسه إذا نُفِّذ من حاوية --network host ليس دليلًا على الجسر.

# host namespace
ip route get 1.1.1.1
ip -brief addr show

# a fresh container on the same bridge network
docker run --rm --network appnet alpine sh -c 'ip route; cat /etc/resolv.conf; ip -6 route'

ثم كرّر الاختبار داخل حاوية التطبيق الحقيقية بدلًا من صورة مشابهة. فقد يحمل التطبيق مسارًا إضافيًا أو متغير بيئة لوكيل أو مُحلِّلًا مختلفًا، وكل واحد من ذلك يغيّر الإجابة. افحص تحليل الأسماء وعائلة العناوين الثانية في كل مرة: الحاويات على الجسور المعرّفة من المستخدم تُحل عبر مُحلِّل Docker المدمج عند 127.0.0.11، ويمكن لمسار افتراضي IPv6 على الجسر أن يُخرج الحركة بينما تكون منشغلًا باختبار نفق IPv4 فقط.

اقرأ النمط قبل أن تلمس بيانات الاعتماد

عندما يعمل المضيف ولا تعمل الحاوية، يكون السبب بنيويًا في كل مرة تقريبًا، وتدوير المفاتيح أو إعادة تثبيت العميل يهدر بعد ظهر كامل. صنّف العَرَض أولًا وعادةً ما يسمّي الإصلاح نفسه.

What you seeUsual causeFirst check
Host exits through the VPN, container shows the ISP addressThe container never entered the tunnelDefault route inside the container
Container works until the daemon restarts, then stopsRules outside the supported hook, or a changed backendDaemon's reported firewall backend and DOCKER-USER
Container loses internal hosts after the tunnel comes upVPN prefix overlaps the Docker bridge subnetip route on the host, then docker network inspect
Small replies arrive, large ones hangTunnel MTU or missing MSS clampingLink MTU on both ends of the tunnel
Container falls back to the ISP address when the tunnel dropsNothing enforces the kill switch for forwarded trafficStop the tunnel with a request in flight

صف التداخل يستحق جملة خاصة به. ملف تعريف VPN يدفع مسارًا للنطاق 172.17.0.0/16، أو للنطاق 10.0.0.0/8 الذي يصادف أنه يحتوي بادئة الجسر لديك، يجعل النفق يدّعي شبكة الحاويات الفرعية، وستتجه الردود إلى العناوين المترجمة في الاتجاه الخطأ أو تختفي. إعادة ترقيم شبكة Docker عادةً أنظف من تكديس الاستثناءات.

اجعل التغطية صريحة، ثم اكسرها عمدًا

هناك تصميمان يصمدان أمام المراجعة. شارك نطاق أسماء حاوية VPN وستستخدم كل حِمل عمل مغطى نفقًا واحدًا بحد إعادة تشغيل واحد، وهو أمر بسيط حتى تحتاج إحدى الخدمات إلى مخرج مختلف أو مسار DNS خاص بها. أو وجّه شبكة الحاويات إلى بوابة VPN على المضيف: مع تمكين التمرير، وتوجيه بادئة الجسر إلى النفق، ومعالجة حركة العودة صراحةً. يشتري ذلك تحكمًا لكل شبكة ويكلفك مجموعة قواعد عليك صيانتها عبر ترقيات البرنامج الخفي والعميل.

في كلتا الحالتين، الاختبار المهم هو حالة الفشل. أوقف النفق مع وجود طلب حاوية قيد التنفيذ وراقب إلى أين تذهب الحزمة. إذا تراجعت إلى المسار المباشر، فلم تُفرض التغطية أبدًا، لأن مفتاح الإيقاف في العميل يحكم حركة العميل نفسه وليس الحزم المُمرَّرة من جسر. أعد تشغيل البرنامج الخفي والمضيف بعد ذلك وأكّد النتيجة مرة ثانية؛ فهذه هي اللحظة التي تختفي فيها القواعد المكتوبة يدويًا.

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

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