حتى حاسوب محمول خلف NAT لدى مزوّد الخدمة يستطيع خدمة زميل، ما دام خادم VPN هو نقطة اللقاء. هناك آليتان للوصول: إما أن يتصل العميل إلى الخارج ويطلب من الخادم الاحتفاظ بمنفذ استماع، أو أن ينشر الخادم منفذًا ويترجمه داخل النفق. كلتاهما تحلّان مشكلة الوصول نفسها وتتصرفان بشكل مختلف عند الفشل والإشراف والتسجيل. ثلاثة شروط تحدد أيّهما يناسب إعدادك.

شكلان ونقطة لقاء واحدة

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

ssh -N -R 8081:127.0.0.1:8080 -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 [email protected]

في الشكل الثاني يملك الخادم المنفذ العام و يعيد كتابة كل اتصال نحو عنوان النفق الخاص بالعميل. يتطلب ذلك تمكين تمرير IP، وترجمة الوجهة عند الدخول، وترجمة المصدر عند الخروج، ويستمر في العمل حين لا توجد أي جلسة SSH. المنفذ ملك للخادم لا للجلسة، وهذه هي الخاصية التي تحسم معظم الحالات الواقعية.

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

الشرط الأول: هل يجب أن يعيش المنفذ أطول من الجلسة

تعيش إعادة التوجيه العكسية مدة جلسة SSH التي أنشأتها بالضبط. وعندما ينقطع الرابط يختفي المستمع ويرى الزميل اتصالًا مرفوضًا بدل مسار بطيء. ومراقبة الأمر بوحدة systemd وسياسة إعادة تشغيل تعالج ذلك، ويجعل ExitOnForwardFailure=yes فشل الربط ظاهرًا فورًا بدل ترك جلسة تعمل دون أي إعادة توجيه.

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

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

الشرط الثاني: من يملك الجدار الناري والسجلات

الشكل العكسي يحتفظ بكل السياسة في مكانين. يقرر sshd ما إذا كانت عمليات إعادة التوجيه البعيدة مسموحًا بها أصلًا عبر AllowTcpForwarding، ويقرر GatewayPorts ما إذا كان المستمع يرتبط بواجهة الاسترجاع أم بكل العناوين. ومع القيمة الافتراضية no لا يستطيع زميل خارج الخادم الوصول إلى المنفذ رغم نجاح إعادة التوجيه، ويبدو ذلك كنفق معطوب مع أنه في الحقيقة عنوان ربط.

sudo ss -ltn '( sport = :8081 )'
sudo grep -E '^(GatewayPorts|AllowTcpForwarding)' /etc/ssh/sshd_config

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

sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8081 -j DNAT --to-destination 10.88.0.6:8080
sudo iptables -t nat -A POSTROUTING -o tun0 -m conntrack --ctstate DNAT -j SNAT --to-source 10.88.0.1

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

الشرط الثالث: منفذ واحد أم منافذ كثيرة، ومن يملك الاسم

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

الأسماء تزيد الأمر تعقيدًا. يمكن أن تقع إعادة التوجيه العكسية خلف وكيل TCP يوجّه حسب SNI، بينما المنفذ المترجم عادةً منفذ واحد لكل خدمة. وإذا كانت الخدمة تنهي TLS بنفسها وتحتاج اسم المضيف الأصلي، فنهج الوكيل يحفظه، ونهج DNAT يحفظه فقط إذا قبلت الخدمة ذلك الاسم على ذلك المنفذ.

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

قرّر، ثم اختبر من الخارج

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

sudo iptables -t nat -L PREROUTING -n -v
sudo tcpdump -ni any 'tcp port 8081' -c 20

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

بعد أن يعمل الشكل، سجّل المنفذ والمالك وطريقة الإشراف بجانب إعداد النفق. إصلاح وصول موجود فقط في سجل أوامر شخص ما يبعد إعادة تشغيل واحدة عن حادثة متكررة.

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