proxy_redirect لا يصل NGINX بمضيف VPN الخاص بك
proxy_redirect يعيد كتابة ترويسات في استجابة وصلت بالفعل؛ وهو لا يختار الخادم الأعلى أبدًا. تحقق من proxy_pass، ثم المسار إلى الخادم الخلفي، ثم الترويسات.
يحتوي الاسم على كلمة redirect، لذا يُلصق داخل كتلة location عندما يتعذر الوصول إلى خادم خلفي وراء الـ VPN. لا شيء يتغير، والاستنتاج البديهي أن التوجيه معطوب أو يحتاج إلى صياغة مختلفة. ما حدث أبسط وأقل إطراءً: يعمل proxy_redirect على استجابة عادت بالفعل، وفي هذا النشر لم يصل أي طلب إلى ذلك الحد.
توجيهان، لحظتان في طلب واحد
يمر طلب HTTP عبر وكيل عكسي بعدة قرارات بالترتيب، ويقع التوجيهان في طرفين متقابلين من ذلك التسلسل. أحدهما يختار إلى أين يذهب الطلب. والآخر يعدّل ترويسات معينة في الإجابة التي تعود.
| Directive | When it acts | What it can change |
|---|---|---|
proxy_pass | Before any bytes leave the proxy | Which upstream receives the request |
proxy_redirect | After the upstream responds | Matching Location and Refresh text |
هذا الترتيب هو الإجابة كلها. إذا لم يُنفَّذ الصف الثاني أبدًا لأن الأول فشل، فالتوجيه الثاني ليس مُعدًّا بشكل خاطئ، بل هو ببساطة غير قابل للوصول. لا مقدار من إعادة كتابة السطر الثاني سيُنشئ الاستجابة التي كان المفروض أن يعدّلها. شخّص من الصف الأول إلى الخارج، فيتحول السلوك المربك إلى مسار مفقود أو اتصال مرفوض.
اختيار الخادم الأعلى يخص proxy_pass
لنفترض أن NGINX يعمل على مضيف دخول عام ويمكنه الوصول إلى تطبيق على 10.40.0.20:8080 عبر الـ VPN الخاص به. الشظية التي تختار ذلك التطبيق تبدو هكذا، داخل كتلة server قائمة:
location / {
proxy_pass http://10.40.0.20:8080;
}
استخدم المخطط والعنوان والمنفذ الحقيقيين، وتعامل مع هذا كشظية لا كنشر كامل. على مضيف الدخول أيضًا أن يحتفظ بمسار الـ VPN، ومسار تمرير مسموح به، وحركة عودة عاملة إلى تلك الخدمة، لأن الوكيل الذي يستطيع الوصول إلى عنوان على الورق لا يزال يحتاج إلى موافقة النواة.
يبقي مرجع وحدة proxy اختيار الخادم الأعلى منفصلًا عن إعادة كتابة ترويسات الاستجابة، ويشير إلى أن قيمة proxy_pass التي تحتوي على URI تغيّر طريقة استبدال بادئة location المطابقة. وإضافة مكونات المسار أو إزالتها دون التحقق من عنوان URL الذي يتوقعه التطبيق طريقة موثوقة لإنتاج 404 يبدو كفشل في التوجيه.
proxy_redirect يصلح الإجابات التي تسرّب عنوانًا خاصًا
بمجرد أن يتدفق الحركة، قد يجيب خادم خلفي بترويسة Location تذكر عنوانه الخاص. المتصفح الذي يتبع تلك الترويسة يترك نقطة الدخول العامة ويحاول الوصول إلى شيء لا يستطيع تحليله. إعادة كتابة الاستجابة المُعدّة عمدًا تُسقط عنوان URL الخاص على العنوان العام:
proxy_redirect http://10.40.0.20:8080/ https://app.example.com/;
استبدل الطرفين بقيم حقيقية. وافهم النطاق الضيق أيضًا: يُعاد كتابة نص ترويسات Location و Refresh المطابقة، أما عناوين URL المضمنة في HTML أو JavaScript أو الملفات التي جرى تنزيلها فلا.
إذا كان التطبيق يبني روابط مطلقة في كل مكان، فالإصلاح الدائم هو إعداد عنوان URL الخارجي الخاص به، لا قائمة متنامية من قواعد إعادة الكتابة على الوكيل. وإضافة قواعد حتى تبدو المخرجات صحيحة تنتج إعدادًا يفشل في أول صفحة لم يختبرها أحد. إعداد تطبيق واحد صحيح يحل محل المجموعة بأكملها.
ما لا تستطيع إعادة كتابة الترويسة إصلاحه
تبدو مشكلات مجاورة عدة كأنها مشكلات إعادة توجيه وليست كذلك. قد تحتاج ترويسة Host المرسلة إلى الأعلى إلى مطابقة المضيف الافتراضي للخادم الخلفي. وقد يحتاج خادم TLS أعلى إلى اسم خادم محدد مع التحقق من الشهادة، وإعادة كتابة ترويسة استجابة لا تفعل شيئًا لأي منهما.
نطاق الكوكيز وسمات النطاق تخص التطبيق وإعداده. يستطيع الوكيل إسقاط الترويسات أو إعادة كتابتها طوال اليوم ومع ذلك ينتج جلسة تفشل في الطلب الثاني، لأن الكوكي صدر لمضيف لم يزره المتصفح قط. يبدو ذلك الفشل متقطعًا، ولهذا يصمد طويلًا في قائمة التذاكر. وقراءة نطاق الكوكي تنهي التحقيق عادة في دقيقة.
أبقِ المصادقة واختيار الخادم الخلفي مقيدين بالتطبيق المقصود أيضًا. ينبغي أن يعرّض وكيل عكسي عام تطبيقًا واحدًا عبر VPN الخادم بدلًا من أن يصبح بوابة عامة لكل عنوان خاص يستطيع ذلك المضيف الوصول إليه. إن location عامة واحدة تمرر أي شيء يطلبه المتصل تحوّل خدمة واحدة مكشوفة إلى خريطة لشبكتك الخاصة. سمِّ الخادم الأعلى صراحةً وأبقه هناك.
اختبر بالترتيب الذي يسير به الطلب
أكّد ثلاثة أمور بالترتيب: أن NGINX اختار location المقصودة، وأنه أكمل طلبًا إلى الخادم الخلفي، وأن المتصفح تبع أي إعادة توجيه لاحقة وحمّل الموارد الفرعية. لكل خطوة سطور سجل خاصة بها، وقراءتها بالترتيب تحول 502 الغامض إلى نتيجة محددة.
التمييز الذي تحتاجه هو بين اتصال أعلى فاشل ومتصفح أُرسل إلى اسم خاص غير قابل للوصول. الأول يظهر في سجل أخطاء الوكيل؛ والثاني يظهر كطلب لا يصل أبدًا، مع شكوى المتصفح من مضيف لا يستطيع تحليله. مشكلتان مختلفتان، وملفان مختلفان، وواحدة منهما فقط تتضمن proxy_redirect إطلاقًا.