ما الذي يخبرك به REMOTE_ADDR في PHP فعلاً خلف VPN
إنه قيمة قدّمها خادم الويب لديك، وليس استعلامًا داخل النفق. تتبّع مسار الطلب، وتحقق من يمكنه إعادة كتابته، وأبقِ الهوية في التطبيق.
يسأل أحدهم لماذا يظهر مستخدم VPN في سجل التطبيق بعنوان يخص البوابة، أو بعنوان تغيّر بعد الغداء. تبدأ الإجابة بما هي هذه القيمة: قيد وضعه خادم الويب في بيئة الطلب. ليست استعلامًا داخل النفق، وليست هوية شهادة، وليست وعدًا بأن الرقم يخص شخصًا واحدًا. قراءتها كأي من هذه الثلاثة تُنتج إجابات واثقة خاطئة بطرق مختلفة.
القيمة تأتي من الخادم، لا من النفق
يتلقى PHP بيئة الطلب من الشيء الذي نفّذ السكربت. يصف مرجع متغيّرات الخادم في PHP هذه القيود بأنها من إنشاء خادم الويب، وتوافرها يعتمد على كيفية وصول الطلب.
السكربت الذي يعمل كخطاف سطر أوامر في VPN هو سياق تنفيذ مختلف تمامًا. لا يملك طلب ويب، ولا مقبس عميل، ولا REMOTE_ADDR، ولهذا فإن كود الويب المنسوخ داخل خطاف يعطي قيمًا فارغة بدلًا من قيم خاطئة. للخطاف بيئته الخاصة التي يملأها البرنامج الخفي، وهي موثّقة على حدة. البحث هناك عن REMOTE_ADDR هو بحث عن متغيّر لم يُضبط قط.
أبقِ هذا الفرق في ذهنك قبل أن تقارن سجلين. ربما تقارن طلب صفحة بخطاف، وهذه ليست مقارنة على الإطلاق. تحقق من سياق التنفيذ أولًا ومن العنوان ثانيًا.
تتبّع مسار الطلب قبل أن تثق بالرقم
العنوان المُبلَّغ هو النظير للاتصال الذي رآه خادم الويب. ضع أي شيء بين العميل وذلك الخادم، فيتغيّر النظير. الترجمة والإنهاء وموازنة الحمل كلها تنقل الملاحظة خطوة إضافية بعيدًا عن المستخدم.
أربعة مسارات شائعة تُنتج أربع ملاحظات مختلفة.
| Path to the listener | What can be reported |
|---|---|
| Client routed straight to the private listener, no translation | The client's tunnel address |
| Gateway translates the source before forwarding | The gateway's translated address |
| Reverse proxy terminates the client and opens its own backend connection | The proxy's backend address |
| Load balancer in front of two proxies | Whichever hop the server treats as its peer |
اكتب المسار مع اسم الوجهة وعائلة العناوين وكل نقطة ترجمة. من دون هذه الخريطة، تبدو القيمة الصحيحة والقيمة الخاطئة متطابقتين في سطر السجل. سطران من المخطط يوفّران بعد ظهر كامل من الجدل.
الاستبدال يحدث فقط حيث يكون مُهيَّأ
يمكن للخادم أو الإطار أن يستبدل عنوان العميل عمدًا. وحدة remote-IP في Apache ووحدة real-IP في NGINX تفعلان ذلك، والقيمة التي يتلقاها PHP تعتمد على هذه التهيئة وعلى المعطيات الممرّرة إلى معالج السكربت.
إذن REMOTE_ADDR ليس دائمًا النظير TCP غير الممسوس. إنه النظير كما اختار الخادم أن يبلّغ عنه بعد تطبيق سياسته الخاصة. هذا الفرق يحدد ما إذا كانت القيمة دليلًا أم زينة.
اسأل مالك الخادم أي حقل هو المرجع في هذا النشر وكيف يُحفظ النظير الأصلي عند حدوث الاستبدال. إن لم يستطع أحد الإجابة، فالسجل لا يثبت شيئًا بعد.
لا تقرأ رؤوس التمرير على الثقة
يمكن للمتصل أن يرسل رؤوس التمرير بنفسه. اعتبار القيد الأول المفصول بفاصلة عنوانًا موثّقًا للمستخدم هو قرار بالثقة بكل من يتصل، وهو عكس ما يهدف إليه الرأس. يصف الرأس سلسلة، ولا يمكن إلا لطبقة موثوقة أن تضمن تلك السلسلة.
استخدم دعم البروكسي الموثوق في الخادم أو الإطار مع سلسلة البروكسي الفعلية مهيأة، ودعه يتخلص من القيم القادمة من مصادر خارج تلك السلسلة. التحليل المكتوب يدويًا هو المكان الذي تسكن فيه معظم الأعطال المثيرة.
العنوان الذي يبلّغ عنه البروكسي لا يغيّر أيضًا مصدر الحزم الذي تراه جدار حماية أعلى. أبقِ بيانات HTTP الوصفية وتصفية الشبكة ملاحظتين منفصلتين، لأنهما تجيبان عن سؤالين مختلفين.
استخدم هوية التطبيق للقرارات
للوصول إلى سجلات مستخدم، اعتمد على الكيان الموثّق وقواعد التفويض في التطبيق. يمكن إعادة تخصيص عنوان داخلي، ويمكن لعنوان مترجم واحد أن يمثل مئات المستخدمين المتزامنين. لا تستطيع أي من هاتين الخاصيتين إصلاحهما مراجعة العنوان.
إذا احتاج التشغيل إلى ربط طلب بجلسة VPN، فاضمم العنوان المُراقَب والطابع الزمني إلى سجلات الجلسات المرجعية وفق نموذج الترجمة الذي وثّقته. ينتج عن ذلك ارتباط يمكنك الدفاع عنه؛ والعنوان وحده لا يفعل ذلك.
للتشخيص، سجّل الحقول القليلة التي تحتاجها بدلًا من مصفوفة الخادم كاملة، التي قد تحمل رؤوسًا ومواد مصادقة. الاستنتاج المفيد يقول ما تعنيه هذه القيمة في هذا النشر، لا أي قيمة تبدو أكثر شبيهًا بعميل.