Pi كعميل VPN: مدير واحد أم سكربت مخصص؟
مقارنة بين ملف تعريف في NetworkManager وسكربت عميل مكتوب يدويًا على Raspberry Pi، بما في ذلك النفق الكامل وDNS وIPv6 والسلوك عند سقوط النفق.
إن Raspberry Pi التي تحتاج فقط إلى حماية حركة المرور الصادرة الخاصة بها لديها تصميمان واقعيان: أن يملك مدير الشبكة النفق، أو أن تحتفظ بسكربت يملكه. كلاهما يستطيع حمل الحركة. لكنهما يفشلان في مواضع مختلفة، والفشل الذي تستطيع تشخيصه عن بُعد في الثانية صباحًا هو الفشل الذي يستحق الاختيار. قارنهما من حيث الملكية، ومن حيث ما يعنيه النفق الكامل عندما يدخل IPv6 وDNS في الصورة، ومن حيث ما يحدث في اللحظة التي يسقط فيها النفق.
مالكان لنفق واحد
التصميم A هو ملف تعريف داخل مدير الشبكة في النظام: ملف OpenVPN مستورد أو اتصال WireGuard أصلي، يُنشَّط عند الإقلاع بواسطة الخدمة نفسها التي ترفع Ethernet وWi-Fi. التصميم B هو وحدة من صنعك تشغّل العميل مباشرة، وتعدّل إعدادات المُحلِّل، وتثبّت مساراتها وقواعد جدار الحماية الخاصة بها. كلاهما تصميم مشروع؛ والفرق بينهما في مَن يُسمح له بتغيير جدول التوجيه.
تختلف حالات الفشل لأن المالكين مختلفون. في التصميم A، ملف تعريف لا يُنشَّط يُبقي الواجهة قائمة والنفق معطلاً، وسجلات المدير تقول السبب. في التصميم B، سكربت ينجح جزئيًا يترك مسارات تبقى بعد العملية التي أنشأتها. تشغيل الاثنين معًا أسوأ نتيجة: عمليتان تكتبان المسار الافتراضي، وتعديلان للمُحلِّل يتسابقان عند الإقلاع، ومجموعتان من الأسرار يجب تدويرها.
اختر مالكًا واحدًا لكل نفق وعطّل الآخر قبل أن تختبر أي شيء. مالكَان يعنيان أيضًا مكانين للنظر عندما يكون النفق قائمًا ولا يُحلّ أي اسم. هذه القاعدة الواحدة تمنع معظم الحالات المربكة الموصوفة في نقاشات Pi VPN.
ما الذي ينشئه الاستيراد، وما الذي لا ينشئه
على Raspberry Pi OS Bookworm وما بعده، أداة إعداد الشبكة الافتراضية هي NetworkManager، لذا فملف التعريف هو الموطن الطبيعي لنفق عميل. يحتاج الاستيراد إلى تثبيت الملحق المطابق؛ وبدونه يفشل الاستيراد برسالة عن نوع اتصال غير مدعوم، وهي الإشارة الصادقة إلى التوقف وتثبيت الملحق.
nmcli connection import type openvpn file ./provider.ovpn
nmcli connection show
nmcli --ask connection up id provider-name
الاستيراد يخزّن ملف تعريف. وهو لا يثبت أن الطرف الآخر قابل للوصول، ولا يضمن أن كل توجيه في الملف نجا من التحويل. اقرأ الاتصال الناتج مرة أخرى وافحص الأجزاء التي تحمل الهوية والثقة: الشهادة، والمضيف البعيد والمنفذ، وما إذا كانت كلمة المرور تُطلب أو تُخزَّن.
التنشيط باستخدام --ask يبقي عبارة المرور خارج سجل الصدفة على جهاز مشترك. أما بالنسبة إلى Pi غير المراقب فسوف تريد في النهاية أن يبدأ ملف التعريف عند الإقلاع، وهذا قرار منفصل عن تشغيله مرة واحدة يدويًا.
النفق الكامل، بمقارنة بين التصميمين
النفق الكامل ادعاءٌ عن المسارات، لا عن النية، والتصميمان يعبّران عنه بطريقتين مختلفتين. نهج ملف التعريف يطلب من المدير تثبيت مسار افتراضي وإعدادات المُحلِّل الخاصة به؛ ونهج السكربت يفعل ما يقوله السكربت، بما في ذلك لا شيء. لا يغطي أي من التصميمين IPv6 إلا إذا طُلب منه ذلك، والمسار الافتراضي IPv6 غير الملموس سيحمل الحركة بسعادة خارج النفق بينما يبدو IPv4 مثاليًا.
ip -4 route get 198.51.100.23
ip -6 route show default
resolvectl query example.org
استخدم عنوانًا توثيقيًا لاستعلام المسار واستبدل به مضيفًا يُسمح لك بفحصه. الأمر الأول يُظهر الواجهة التي سيستخدمها Pi لوجهة عادية؛ والثاني يُظهر ما إذا كان المسار الافتراضي IPv6 لا يزال موجودًا؛ والثالث يُثبت أي مُحلِّل أجاب. اقرأ الثلاثة قبل أن تصدّق أي ادعاء عن نفق كامل.
إذا وعدت تعليمات المزوّد بنفق كامل لكن المسار الافتراضي IPv6 بقي، فإن Pi يسرب. عطّل IPv6 على الوصلة الصاعدة أو اطلب من ملف التعريف أن يطالب به، وقرّر بوعي بدلًا من أن تكتشف ذلك لاحقًا.
الفشل المفتوح مقابل الفشل المغلق
عندما يسقط النفق، فإن جدول توجيه يفقد مساره الافتراضي يعود ببساطة إلى الوصلة الصاعدة الفيزيائية، وتستمر الحركة في العراء. هذا هو الفشل المفتوح، وهو السلوك الافتراضي لكل من التصميمين ما لم يمنعه شيء. يكتشفه معظم الناس بعد أسابيع بقراءة سجل جدار الحماية.
الفشل المغلق يكلفك الوصول البعيد عندما يكون النفق معطلاً، لذا يحتاج إلى استثناء متعمد لمسار الإدارة. إحدى الطرق قاعدة تسمح فقط بعنوان نظير VPN خارج النفق:
sudo nft add table inet vpnkill
sudo nft 'add chain inet vpnkill out { type filter hook output priority 0; policy accept; }'
sudo nft add rule inet vpnkill out oifname != "tun0" ip daddr != 203.0.113.24 reject
قارن التكلفة التشغيلية بصدق. لا يستطيع ملف التعريف عادةً التعبير عن هذه القاعدة، لذا يدفعك الفشل المغلق نحو تصميم السكربت أو نحو وحدة صغيرة تثبّت القاعدة بشكل مستقل عن النفق. في كلتا الحالتين، سجّل حالات الرفض لأسبوع: فالرفض الصامت يبدو مطابقًا لخدمة معطلة، وستحتاج العدّاد عندما يبلّغ مستخدم بأن موقعًا واحدًا توقف عن التحميل.
الاختيار من أجل Pi بلا شاشة
إذا كانت الصورة تشغّل NetworkManager بالفعل، ولا يحتاج النفق إلى شيء غريب، وتريد أن يتبع الوصلة الصاعدة تلقائيًا، فخذ ملف التعريف. وإذا كنت تحتاج إلى توجيه سياساتي، أو عدة أنفاق تُختار لكل وجهة، أو قاعدة فشل مغلق يجب أن توجد قبل أن يبدأ النفق، فخذ السكربت وامتلك كل جزء منه، بما في ذلك ترتيب الإقلاع والتنظيف. خلط التصميمين يكلّف أكثر من أي منهما وحده.
الترحيل بينهما مسألة ترتيب في الأساس: عطّل المالك القديم، وتأكد من عدم بقاء أي مسار أو إدخال مُحلِّل قديم، ثم فعّل الجديد وأعد التشغيل مرتين. إعادة تشغيل واحدة قد تخفي سباقًا تكشفه الثانية. اختم باختبار Pi لا النفق: حلّ اسمًا، وجلب شيئًا عبر IPv4، وجلب عبر IPv6 إذا أبقيتها، ثم أسقط النفق وتأكد من أن السلوك الذي اخترته يحدث فعلًا. وجود واجهة في ip link هو بداية الاختبار، لا نهايته.