النفق الكامل في OpenVPN يقطع جلسة SSH لديك: أصلح مسار الرد
أخذ المسار الافتراضي يدفع ردود SSH إلى النفق. ثبّت النظير، أو صفِّ redirect-gateway، أو وجّه حسب المصدر قبل أن تفقد الخادم.
تشغيل عميل OpenVPN بنفق كامل على جهاز تصل إليه عبر SSH قد يقطع الجلسة في أقل من ثانية، والجهاز لا يفعل شيئًا خطأ. النفق لا يغيّر طريقة وصول الحزم إلى الخادم؛ بل يغيّر طريقة خروج الردود. وبمجرد أن يشير المسار الافتراضي إلى tun0، يذهب الرد إلى عميل SSH لديك داخل شبكة المزوّد، التي لا تملك مسارًا راجعًا إلى عنوانك. يتعطّل الاتصال، وتنتهي المهلة في المحاولة التالية، بينما لا يزال البرنامج الخفي يستمع على المنفذ 22 طوال الوقت.
اقرأ جدول التوجيه قبل أن تقرأ سجل VPN. سيقول السجل إن النفق قد ارتفع، وهو محق. السؤال هو إلى أي واجهة يُسلَّم كل رد، وهذا بحث لكل حزمة على حدة في جدول أعاد النفق كتابته للتو.
لماذا يخرج الرد من الباب الخطأ
لا تزال الحزم الواردة تصل عبر الواجهة الفيزيائية، لأن عميل VPN لا يمكنه تغيير طريقة وصول الإنترنت إلى العنوان العام لخادمك. الردود قرار منفصل: فلكل حزمة يبحث النواة عن الوجهة، وبعد --redirect-gateway تقول المدخلة الافتراضية نفق. يرى مخرج المزوّد وجهة لا يخدمها فيُسقط الحزمة.
حماية OpenVPN نفسها تغطي وجهة واحدة فقط. يصف دليل الإصدار 2.6 الخيار --redirect-gateway كسلسلة: يضيف مسار مضيف لنظير VPN عبر البوابة المستخدمة قبل النفق، حتى لا يمكن لحركة المرور المشفّرة أن تعود إلى نفسها، ثم يستبدل المسار الافتراضي. ذلك المسار المضيف مخصص للنظير وحده. عميل SSH لديك مجرد عنوان إنترنت آخر ولا يحصل على أي استثناء.
من المفيد استبعاد خطأ بادئة واحد مبكرًا. الأمر ip route add -net 0.0.0.0 gw 10.8.0.1 dev tun0 بلا طول يطابق العنوان المفرد 0.0.0.0، لا الإنترنت؛ ويجب أن يكون 0.0.0.0/0. وإذا كان أخذ المسار الافتراضي يكسر نقل النفق نفسه، أضف نقطة النهاية كمسار مضيف عبر الواجهة الفيزيائية باستخدام عنوان المزوّد الحقيقي.
ثبّت عنوان عميل SSH لديك لإصلاح فوري
أسرع إصلاح هو مسار مضيف لعنوان عميلك عبر البوابة التي استخدمها الخادم قبل وجود النفق. من جهتك، ابحث عن العنوان الذي سيراه الخادم، ثم اقرأ جدول الخادم لتعرف البوابة القديمة:
curl -s https://ifconfig.co
ip route
على الخادم، أضف الاستثناء قبل أن يبدأ العميل. العناوين هنا عناصر نائبة؛ الشكل هو ما يهم:
sudo ip route add 80.128.240.55 via 192.168.178.1
هذا هو الإصلاح المستخدم في الحالة المبلَّغ عنها، وهو يعمل فورًا. وهو أيضًا هشّ بطريقتين متوقعتين: يختفي المسار عند إعادة التشغيل، ويصبح خاطئًا في اللحظة التي يمنحك فيها مزوّد الخدمة عنوانًا مختلفًا. تعامل معه كإجراء طارئ واجعله دائمًا عمدًا، عبر وحدة شبكة أو خطاف موزّع، أو اقبل أنه مؤقت واكتب مسار الاستعادة.
امنع العميل من أخذ المسار الافتراضي
الخيار الأنظف هو منع النفق من استبدال المسار الافتراضي أصلًا. الخيار route-nopull، المستخدم مع --client أو --pull، يقبل الخيارات المدفوعة باستثناء المسارات وخيار block-outside-dns وخيارات على نمط DHCP مثل خوادم DNS، فلا تُضيف إلا البادئات التي تحتاجها. أداة أضيق هي مرشّح السحب، الذي يُسقط توجيهًا واحدًا مسيئًا ويحتفظ بالباقي:
route-nopull
pull-filter ignore "redirect-gateway"
استخدم أحدهما دون الآخر، وكن واضحًا بشأن ما يتغيّر. بدون مسار افتراضي عبر النفق، لم يعد الخادم يتصفح الإنترنت عبر المزوّد؛ بل يصل فقط إلى ما وجّهته صراحة. وإذا كان النفق الكامل هو الغرض كله من الإعداد، فهذا هو المفتاح الخاطئ والمسار المضيف أعلاه هو الصحيح.
اقسم مسار العودة حسب المصدر أو حسب الاتصال
عندما يكون العنوان الوارد ثابتًا، تُبقي قاعدة المصدر الردود محلية دون المساس بمسارات النفق نفسها. أعطِ عنوان الواجهة الفيزيائية جدوله الخاص الذي يحتوي بادئة LAN والافتراضي الفيزيائي، ثم اختر ذلك الجدول لحركة المرور الصادرة منه:
ip rule add from 192.168.1.11 table 128
ip route add table 128 to 192.168.1.0/24 dev eth0
ip route add table 128 default via 192.168.1.1
يعمل هذا لأن الردود على اتصال SSH وارد تكون صادرة من العنوان الذي اتصل به العميل. استخدمت حالة مبلَّغ عنها، كان فيها كل خدمة واردة يجب أن تستمر في العمل، هذا الشكل بالضبط. وعندما يكون العنوان الوارد متغيّرًا أو المسار ديناميكيًا، ضع علامة على الاتصال بدلًا من ذلك: عيّن علامة conntrack على أول حزمة تصل من الواجهة الفيزيائية، وانسخها إلى حزم الرد في OUTPUT، ووجّه الحزم المعلَّمة عبر جدول يشير إلى البوابة الفيزيائية.
iptables -t mangle -A PREROUTING -i eth0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1234
iptables -t mangle -A OUTPUT -m connmark --mark 1234 -j MARK --set-mark 4321
ip route add default via 192.168.1.1 dev eth0 table 3412
ip rule add fwmark 4321 table 3412
أبقِ علامة الاتصال وعلامة جدار الحماية ورقم الجدول متمايزة أثناء الاختبار. إعادة استخدام رقم واحد لدورين تنتج قاعدة تبدو صحيحة وتطابق الحزم الخطأ. تحتاج المدخلة الافتراضية للجدول أيضًا إلى via مع بوابة LAN على وصلة إيثرنت عادية؛ المدخلة الافتراضية المجردة dev eth0 تعمل فقط عندما تكون الواجهة نقطة إلى نقطة أو يُحلّ القفزة التالية بطريقة أخرى. صادف أن مضيف Jessie المبلَّغ عنه كان على وصلة عمل فيها الشكل المجرد، وهذا ليس قاعدة توزيعة تُنسخ.
تحقّق دون أن تُقفل نفسك بالخارج
لا تختبر بفصل الاتصال. أبقِ الجلسة الأولى مفتوحة، وارفع النفق، واسأل النواة أي مسار سيسلكه عنوانك:
ip route get 80.128.240.55
يجب أن يذكر الجواب الواجهة الفيزيائية والبوابة القديمة، لا النفق. ثم افتح اتصال SSH ثانيًا؛ فهذا هو الاختبار الحقيقي، لأن الجلسة القديمة قد تبقى على حالة لا يستطيع اتصال جديد إعادة إنتاجها. وإذا تعطّل الثاني بينما لا يزال الأول يجيب، فالقاعدة لم تطابق الحركة المهمة أبدًا، والعلامات أو عنوان المصدر هي موضع البحث.
أبقِ وحدة تحكّم خارج النطاق متاحة طوال التمرين. الخادم الذي يكون مسار وصوله الوحيد هو النفق الذي كسرته للتو لا يمكن إصلاحه عبر ذلك النفق، والتراجع أسهل عندما تكون قد كتبت أرقام الجداول والبادئات التي أضفتها.