الخلاصة

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

لم يكن الخطأ في الفاصلة

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

يوفر المقبس حقيقة أضيق: عنوان العقدة التي أنشأت الوصلة المباشرة. قد تكون موزع حمل لا المستخدم النهائي، لكنها تظل المشاهدة المحلية التي يمكن أن ترتكز إليها سلسلة التفويض.

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

ما يحدده RFC 7239 وما لا يثبته

يعرف RFC 7239 حقل Forwarded الاختياري لكشف معلومات تغيرت أو ضاعت بسبب وسيط. تصف معاملات for وby وhost وproto جوانب مختلفة من قفزة واحدة. ارتباطها مفيد، لكنه لا يصنع اعتماد هوية.

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

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

XFF عقد مختلف

X-Forwarded-For ممارسة واسعة، لكنه ليس الحقل الذي عرفه RFC 7239. يوضح AWS ALB مثلاً ثلاثة أوضاع: الإلحاق والحفظ والحذف. في الإلحاق، يحتفظ بالقيمة الواردة ويضيف إلى اليمين العنوان الذي شاهده. مشاركته تفسر الإضافة، ولا تصادق على ما كتبه العميل إلى اليسار.

يوثق HAProxy إدراج XFF وتوليد Forwarded المعياري على نحو منفصل. لذلك يلزم أن يعرف المستقبل اسم الحقل وموضع الإضافة وسياسة التنظيف وخوارزمية القراءة. لا توجد قاعدة عامة تقول «الأول دائماً» أو «الأخير دائماً» خارج عقد المرسل.

ابدأ من الطرف القابل للرصد

يحدد NGINX عبر set_real_ip_from المرسلين المعروفين بتقديم قيم استبدال صحيحة. ومع real_ip_recursive on يختار آخر عنوان غير موثوق بعد اجتياز الجزء المخول، فيما يحفظ $realip_remote_addr النظير الأصلي.

يفحص Apache mod_remoteip القائمة من اليمين إلى اليسار ويحذر من أن فتح السلوك لوسطاء غير مقيدين يجعل انتحال عنوان آخر أمراً تافهاً. ويعد Envoy القفزات الموثوقة من اليمين وفق إعدادات منها use_remote_address، أو يطبق حدود CIDR معلومة.

لا توجد إذن عملية عامة اسمها «استخرج IP الحقيقي». توجد طوبولوجيا مثبتة لمستمع بعينه. إضافة CDN أو حذف وكيل أو فتح مسار ثان يغير موضع أول عقدة غير موثوقة.

الأسطر المكررة تكشف اختلاف التفسير

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

يكسر IPv6 الفصل الساذج على النقطتين. فالعنوان يحوي نقطتين أصلاً، وقد يضاف منفذ وأقواس واقتباس. يجب اختبار IPv6 مع منفذ، وIPv4 مع منفذ، وunknown، والمعرفات المموهة، والفراغات، والفواصل الرديئة.

التطبيع يجيب عما قرأه النظام. والثقة تجيب لماذا كان للمرسل حق تقديمه. لا يجوز دمج الإجابتين.

لا يمنح host وproto مصادقة

قد يستخدم التطبيق المضيف والبروتوكول المنقولين بعد إنهاء TLS لبناء تحويل أو رابط مطلق أو ملف ارتباط Secure. لكن كتابة العميل proto=https لا تثبت أن الحافة الموثوقة رأت TLS، كما لا يوثق host منقول هوية الأصل.

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

PROXY protocol سجل آخر

يحمل PROXY protocol المصدر والوجهة قبل HTTP. سبقه في الطبقات لا يمنحه مصداقية. على المستقبل توقع مقدمته على مستمع مخصص أو مقيد بشدة، وقبول مرسلين مخولين فقط؛ وإلا استطاع أي عميل كتابة مصدر مختلق قبل أول بايت HTTP.

ينبغي إبقاء النظير الفعلي، وتوقع المقدمة وقبولها، والعنوان المدعى، ثم حقول HTTP، كمشاهدات منفصلة. ضغطها كلها في متغير client_ip يمحو سلسلة الحيازة.

اكتب القاعدة باختبارات الرفض

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

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

يعبر ملف الإعداد عن النية. أما هذه الاختلافات العدائية فتكشف القاعدة التي تعمل فعلاً.