لماذا يضيف خطاف جدار حماية VPN القاعدة نفسها مرتين
قد يعيد إعادة الاتصال تشغيل الخطاف، فصمّم من أجل الحالة المرغوبة: سلاسل مملوكة، واختبار قبل الإدراج، وتغيير واحد متسلسل، وتفكيك ضيق.
يعمل الخطاف في المرة الأولى، وبعد ثلاث عمليات إعادة اتصال تحمل السلسلة ثلاث نسخ من القاعدة نفسها. لم يفشل شيء بصوت عالٍ؛ فقد فعل السكربت ببساطة ما أُمر به في كل مرة يعمل فيها. خطاف VPN عملية إعداد يمكن أن تعمل أكثر من مرة، لذا يحتاج إلى مالك وحالة مرغوبة وتغيير متسلسل. سر بهذا الترتيب تتوقف التكرارات.
امنح القواعد مالكًا قبل كتابة أي منها
حدّد السلسلة أو الجدول الذي تملكه هذه التكاملة قبل أن تكتب قاعدة واحدة. السلسلة المخصصة التي ينشئها الخطاف ويفرغها هي أوضح شكل من أشكال الملكية، لأن التنظيف يمكنه حينها إزالة تلك السلسلة دون المساس بسياسة أي شخص آخر. إن كان لا بد من إضافة قواعد إلى سلسلة مشتركة، فوسمها بتعليق حتى يجد بحث لاحق قواعدك بالضبط. الملكية هي ما يجعل التفكيك آمنًا، والتفكيك هو الجزء الذي يفشل بهدوء.
iptables -N VPN_HOOK 2>/dev/null || true
iptables -C INPUT -j VPN_HOOK 2>/dev/null || iptables -I INPUT -j VPN_HOOK
iptables -S VPN_HOOK
التعليق هنا ليس زينة. إنه الفرق بين إزالة قاعدتك وإزالة قاعدة تصادف أنها تشبهها، وهو يبقى في مجموعة القواعد المحفوظة. اكتب التعليق مرة واحدة في متغيّر، واستخدم النص نفسه في كل أمر يضيف أو يختبر أو يحذف.
اختبر الحالة المرغوبة بدلًا من الإضافة مرة أخرى
اكتب ما ينبغي أن يكون موجودًا ما دام النفق قائمًا: أي واجهات، وأي مصدر ووجهة، وأي بروتوكول وأي منفذ. ثم عبّر عن كل قاعدة كاختبار يتبعه إدراج، حتى يجد التشغيل الثاني القاعدة فلا يفعل شيئًا. يأمر التحقق بالخروج بالصفر عندما تكون القاعدة موجودة، وهذا بالضبط الإشارة التي يحتاجها السكربت. وتوثّق مرجع iptables صيغ التحقق والإلحاق والإدراج المستخدمة هنا.
iptables -C VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT ||
iptables -A VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT
كن حذرًا بشأن الموضع. اختبار قاعدة وإدراجها في الرأس قد ينقل سماحًا إلى ما قبل رفض متعمد كان يأتي أولًا، فيغيّر التشغيل الثاني السلوك حتى وهو لا يضيف شيئًا. ألحق داخل سلسلتك، وتحكّم في الترتيب عبر موضع القفز إلى تلك السلسلة. إن كان الترتيب مهمًا داخل السلسلة، فأعد بناء السلسلة من قائمة معروفة بدلًا من ترقيعها قاعدة بقاعدة.
توقف إذا لم تكن القاعدة التي تحتاجها قابلة للتعبير عنها كاختبار مستقر. وهذا يعني عادةً أن الحالة المرغوبة ما زالت غامضة.
تسلسل التغيير بدلًا من الأمل في ثباته
يمكن أن يتداخل استدعاءان للخطاف، وقد يلاحظ كلاهما غياب قاعدة قبل أن يضيفها أحدهما. خيار الانتظار في xtables يجعل الأمر ينتظر القفل، لكنه لا يجعل تسلسل الاختبار ثم الإضافة ذريًّا عبر أمرين. تسلسل العملية كلها بقفلك الخاص، أو استخدم مديرًا يطبّق دفعة معلنة كمعاملة واحدة. يستطيع nftables فعل الأخير، وهذا أحد أسباب تفضيله على المضيفات التي يتوفر فيها.
flock /run/vpn-hook.lock /usr/local/sbin/vpn-firewall-apply
nft -f /etc/nftables/vpn-hook.nft
أي آلية تختار، أبقِ القسم الحرج قصيرًا واجعله قابلًا لإعادة الدخول: الخطاف الذي يفشل في منتصف الطريق ينبغي أن يكون آمنًا لإعادة التشغيل. سجّل النتيجة حتى يظهر تشغيل متكرر في السجل بدلًا من استنتاجه من عدد القواعد. إذا كان بإمكان مشرفين مختلفين استدعاء الخطاف، فأصلح ذلك أولًا؛ فلا قفل يصلح مالكين اثنين.
فكّك ما تملكه فقط
على التفكيك أن يميّز اتصالًا بديلًا عن الاتصال الذي أزاله، وأن يصمد أمام حدث لا يحصل أبدًا على تنظيف لطيف. احذف بالمعرّفات نفسها التي استخدمتها للإضافة، ولا تفرغ سلسلة مشتركة أبدًا لجعل التنظيف بسيطًا. بعد توقف قاسٍ، شغّل تمريرة مصالحة عند البدء التالي بدلًا من افتراض أن خطاف الإيقاف عمل.
iptables -D VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT
iptables -F VPN_HOOK
ip -brief link show type tun
عمر الواجهة جزء من التصميم أيضًا. قد تنشئ إعادة الاتصال جهازًا باسم مختلف، فتصبح قاعدة تثبّت اسم النفق الثاني قديمة وهي لا تزال تبدو صالحة. فضّل الهوية التي يكشفها الاتصال نفسه، وأعد قراءتها في كل تشغيل. اختبر الأحداث الثلاثة منفصلة: اتصال متكرر، واتصال بديل، وإيقاف. ينبغي أن تصمد حركة المرور المسموحة أمام الثلاثة دون تكرارات، وأن تبقى الخدمات غير ذات الصلة غير متأثرة.
ينتهي العرض التوضيحي عندما يصبح للخطاف مالك، واختبار لكل قاعدة يضيفها، ومسار تسلسلي واحد، وتفكيك يزيل حالته الخاصة فقط. الخطاف الآمن للتشغيل مرتين أثمن من خطاف بارع مرة واحدة.