مفتاح الإيقاف بعد الانتقال من Wi-Fi إلى الخلوي: ما الذي ينكسر
يُكتب مفتاح الإيقاف وفق أسماء الواجهات التي يستبدلها تغيّر الشبكة. تحقّق من المسار الخارجي وعائلات العناوين والمُحلِّل قبل أن تثق به.
في لحظة يكون الحاسوب على شبكة Wi-Fi المكتبية، وفي اللحظة التالية يكون موصولًا بهاتف، ثم يصبح مؤشر النفق أخضر مرة أخرى قبل أن تنتهي من تبديل النوافذ. الضوء الأخضر لا يبلّغ إلا بأن النفق أُعيد اتصاله؛ أما ما فعلته سياسة التوجيه والحجب خلال الفجوة فسؤال آخر. تلك السياسة مجموعة شروط مطابقة بُنيت عند آخر تثبيت لها، وهي تسمّي واجهة وعنوانًا وعائلة عناوين أزالها الانتقال للتو. لذا ينتج عن التبديل نفسه ثلاث نتائج تبدو متطابقة: استمرار الحجب، أو أن تحجب السياسة استعادتها بنفسها، أو أن يُفتح مسار لا يغطيه شيء.
لا شيء على الشاشة يفصل هذه الحالات الثلاث، فاسأل إلى أي معرّفات كانت القواعد مثبَّتة بدلًا من لون المؤشر. على Linux يمكن للقاعدة أن تسمّي واجهة أو مجموعة ipset تُملأ من واجهة؛ وعلى Android يمكن إخبار VpnService بالشبكات الأساسية التي يتبعها عبر setUnderlyingNetworks. كل ارتباط يشير إلى وصلة على وشك الاستبدال، وكل منها يجب إعادة تقييمه بعد ذلك.
ما الذي يعيد الانتقال كتابته فعلًا
عندما تختفي الوصلة القديمة يزيل النواة عناوينها، ويسحب المسارات التي كانت تمر عبرها، ويعيد بناء اختيار عنوان المصدر مما تبقّى. ينتقل المسار الافتراضي إلى البوابة الجديدة، وفهرس الواجهة الذي أشارت إليه القواعد القديمة إما ذهب أو أُعيد استخدامه لجهاز آخر. تُحدَّث أيضًا مُحلِّلات كل وصلة، وإن لم يكن ذلك في اللحظة نفسها مع المسارات. كل هذا يحدث تحت عميل VPN، فالعميل الذي يراقب حالة نفقِه وحده لا يلاحظ شيئًا منه.
المشكلة أن القاعدة تُرمّز معرّفًا محددًا بدلًا من القصد الذي يقف خلفه. القاعدة التي تُسقط كل ما لا يخرج عبر واجهة النفق تُرمّز اسم واجهة؛ والقاعدة التي تسمح بنقطة الطرف تُرمّز عنوانًا قد توجّهه الشبكة الجديدة إلى مكان آخر. وعندما يزول المعرّف لا تصبح القاعدة خاطئة بشكل ظاهر، بل إما تكفّ عن مطابقة أي شيء أو تبدأ بمطابقة الشيء الخطأ.
إعادة بناء النفق الخارجي دون إحداث ثقب
كان النقل الخارجي مربوطًا بعنوان المصدر القديم، لذا عليه فتح مقبس جديد من العنوان الجديد. وعندما تكون نقطة الطرف اسم مضيف لا عنوانًا حرفيًا، يجب أن ينجح الاستعلام ما دام الحجب ساريًا. وهنا فخّ الترتيب: سياسة صارمة بما يكفي لإسقاط كل شيء عدا نقطة الطرف ستُسقط أيضًا الاستعلام اللازم للعثور عليها، إلا إذا جرى التحليل قبل رفع الحجب أو حُمل عبر نفق لا يزال حيًّا. أي ترتيب يمكن أن ينجح، لكن فقط إذا كان العميل يعرف في أي ترتيب هو.
تختلف العملاء هنا على نحو يهمّ عند التشخيص. بعضها يحلّ أولًا ثم يثبّت القواعد بعد ذلك، فيكلّف الانتقال انقطاعًا ظاهرًا ثم يتعافى من تلقاء نفسه؛ وبعضها يُبقي الحجب قائمًا ويعتمد على النفق الباقي لحمل الاستعلام، وهذا يفشل فشلًا تامًا عندما يموت النفق مع الوصلة. وإضافة مسار مباشر افتراضي عريض لاستعادة الاتصال تُنجح الاختبار دائمًا وتُبقي دائمًا على التسريب الذي كنت تمنعه.
المسار الذي لا يزال يشير إلى البوابة القديمة يعطي التعافي المتعثر نفسه من سبب مختلف، فاقرأ الجدول قبل أن تلوم العميل. الأوامر أدناه تسمّي الواجهة وعنوان المصدر اللذين سيستخدمهما النواة حقًّا، وهذا يحسم في سطر واحد ما إذا كان المسار القديم لا يزال مثبَّتًا.
ip route get 1.1.1.1
ip -6 route get 2606:4700:4700::1111عندما تجلب الوصلة الجديدة IPv6 ولا تجلبها القواعد
كثيرًا ما تمنح شبكات الخلوي والشبكات الضيفة بادئة IPv6 عالمية حتى عندما لم تفعل شبكة المكتب السلكية ذلك قط. والسياسة المكتوبة كقواعد IPv4 فقط، وهي الشكل الافتراضي لأكثر وصفات iptables وnftables المصنوعة يدويًا، لا تغطي شيئًا من ذلك. يبقى النفق متصلًا، والتطبيقات التي لديها إمكانية وصول إلى IPv6 تخرج خارجه، ولا يستطيع المؤشر إظهار الفرق لأن النفق قائم فعلًا. والحالة المعاكسة شائعة بالقدر نفسه: مجموعة قواعد خاصة بـ IPv6 وحدها لا تفعل شيئًا على شبكة لا تقدّم v6.
قارن ما تقدّمه الوصلة بما تذكره السياسة، على طرفي الانتقال. هذه الأوامر تطبع الوقائع نفسها التي يعمل بها العميل:
ip -4 route show default
ip -6 route show default
sudo nft list ruleset | grep -c 'ip6 'إذا كان الأمر الثاني يطبع مسارًا افتراضيًا بينما يعيد الثالث صفرًا، فيمكن للوصلة الجديدة أن تُخرج الجهاز عبر IPv6 دون قاعدة تراقبه. أعد تشغيل الأوامر الثلاثة كلها بعد التبديل، لأن الرقم المثير للاهتمام هو الفرق بين التشغيلين. وإذا لم يطبع الثاني شيئًا، تنطبق الحالة المعاكسة، وأي سياسة ثقيلة على v6 تكون هناك زينة فقط.
المُحلِّل ينتقل من يد إلى يد في منتصف الجلسة
المُحلِّلات مرتبطة بالوصلات على الأنظمة الحديثة، فتصل الوصلة الجديدة بمجموعة مُحلِّلات جديدة وربما برؤية split-DNS مختلفة. يحتفظ systemd-resolved بنطاق لكل وصلة ويختار بينها بحسب المسار، بينما يقرأ macOS المُحلِّلات ذات النطاق من المخزن الديناميكي ويراعي ترتيب الواجهات. والعميل الذي يثبّت مُحلِّله الخاص ينافس مُحلِّل الوصلة، وقواعد الأولوية التي لا يراقبها أحد هي التي تحدد الفائز. عندها قد ينكسر تحليل الأسماء بينما يعمل ترشيح الحزم بالضبط كما كُتب له أن يعمل.
اقرأ المُحلِّل النشط لا المُحلِّل المهيّأ. على مضيف systemd يُظهر الأمر الفرعي status من أي وصلة جاء كل نطاق وما إذا كان اسم DNS خاص ساريًا:
resolvectl status --no-pager
resolvectl query intranet.example.comإذا خرج الاستعلام عبر الوصلة الفيزيائية لا عبر النفق، فقد خسر العميل مسابقة الأولوية ولن يُصلح أي ضبط للجدار الناري تسمية الأسماء. قارن مسار الاستعلام على طرفي الانتقال لترى أيّهما تحرّك. والاسم الذي يُحلّ إلى عنوان خاص لا تستطيع الشبكة الجديدة توجيهه هو حالة ثالثة، وهي تظهر كمهلة لا كخطأ.
تدرّب على الانتقال واحفظ السجل
أعد إنتاج التغيّر عن قصد بدلًا من انتظاره. ارفع النفق على الوصلة الأولى، وابدأ نقلًا طويل الأمد واستعلامًا متكررًا، ثم بدّل الوصلة وراقب أيّهما يبقى. سجّل الفاصل بين زوال الوصلة القديمة وإبلاغ النفق بأنه متصل، لأن تلك النافذة هي التي إما صمدت فيها السياسة أو لم تصمد. ونفّذ التسلسل في الاتجاه الآخر أيضًا، كي لا تكون النتيجة من طرف واحد.
الاستثناءات تحتاج مرورًا خاصًّا بها، لأن تجاوزًا مبرَّرًا على الشبكة القديمة ليس مبرَّرًا تلقائيًا على الجديدة. الطابعة أو NAS أو بوابة الأسرى على شبكة المنزل LAN ليس لها نظير على الخلوي، والاستثناء الذي وصل إليها يصبح قاعدة بلا نظير أيضًا.
اكتب أسماء الواجهات والعائلات المعروضة والمُحلِّل الساري وطول الانقطاع لكل اتجاه. إعادة الاتصال تُثبت أن النقل تعافى، لا أن الحجب صمد خلال الفجوة، وهذان ادّعاءان منفصلان يوضعان في تذكرة. وبهذا السجل يُقارن الانتقال التالي بحالة معروفة بدلًا من الذاكرة.