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

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

اتبع الاتصالين، لا سطر السجل

يضاعف Port-Share بروتوكولين على مستمع TCP واحد. يفحص OpenVPN البايتات الأولى من الاتصال الوارد، ويحتفظ به عندما يبدو أنه من بروتوكوله، ويسلّم أي شيء آخر إلى وجهة ثانية. تلك الوجهة عادةً خادم ويب على المضيف نفسه، لذا يكون مقبس خادم الويب المقبول نظيرًا له عملية OpenVPN.

ss -ltnp 'sport = :443'
ss -tnp 'dport = :8080'

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

هذا هو الفحص الذي يحدّد كل شيء آخر. إذا كان نظير الخادم الخلفي هو عنوان المتصفح، فمشاركة المنفذ ليست مشكلتك، بل صيغة السجل.

تمرير النقل ليس حقن ترويسات

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

يمكن لآليتين أن تحملا العنوان الأصلي، وكلتاهما تتطلبان اتفاقًا على الطرفين. يضيف بروتوكول PROXY ترويسة صغيرة إلى مقدمة الاتصال، ويجب أن يكون الخادم الخلفي مهيّأ لتوقّعها؛ والخادم الخلفي الذي لا يتوقّعها سيعامل تلك البايتات كبداية الطلب ويفشل بطريقة مربكة. وتعمل ترويسات الوكيل الموثوقة مثل X-Forwarded-For عندما يضبطها وكيل يدرك HTTP ويُخبر الخادم الخلفي بالنظراء المسموح لهم بتأكيدها.

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

curl -sS -H 'X-Forwarded-For: 127.0.0.1' https://site.example.com/health
grep -F '127.0.0.1' /var/log/nginx/access.log | tail -n 3

دليل تعيين المصدر الاختياري

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

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

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

قرّر أي مكوّن يضمن العنوان

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

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

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

اختبر القاعدة، لا الصفحة

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

curl -sS -o /dev/null -w '%{http_code}\n' https://site.example.com/
tail -n 5 /var/log/nginx/access.log
grep -c '' /var/log/nginx/access.log

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

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

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