شرح مفهوم الـ Reverse Proxy مع بعض تطبيقاته العملية
مقدمة
الـ Reverse Proxy موضوع مهم لمبرمجي الـ Backend، هذا المقال يشرح الـ Reverse Proxy مع توضيحٍ لبعض استخداماته العملية، بالإضافة إلى أمثلة بسيطة باستخدام Nginx على الاستخدامات العملية المشروحة في هذا المقال.
لكن قبل التطرق إلى مفهوم الـ Reverse Proxy يجب شرح الـ Proxy أولا لتتضح الفكرة أكثر.
مفهوم الـ Proxy
الترجمة الحرفية للـ Proxy تعني الوسيط أو الوكيل، فعندما تطلب من شخص ما أن يشتري لك منتجا معينا من أحد البائعين، فهذا الشخص يعتبر وسيطاً بينك وبين البائع (Proxy).
مفهوم الـ Proxy في الاصطلاح التقني، يقصد به الوسيط بينك وبين السيرفر الذي تريد إرسال طلب (HTTP Request) له.
في الوضع الطبيعي، تقوم من جهازك بإرسال طلب (Request) إلى سيرفر الموقع ويقوم الموقع بإرجاع استجابة (Response)، عند دخولك إلى مدونتي لقراءة هذا المقال، المتصفح قام بإرسال Request إلى سيرفر موقعي، وموقعي استجاب بـ Response تحتوي على البيانات التي طلبتَها.
ربما ترغب في إخفاء الـ IP الخاص بك عن المواقع التي تدخل إليها، أو تريد حجب المحتوى أو الإعلانات غير المرغوب بها أو تجاوز حظر بعض المواقع، في هذه الحالة قد تستخدم Proxy Server ليقوم بإرسال الطلب بدلا منك وإرجاع الاستجابة كما في الصورة التالية:
في الصورة السابقة، تلاحظ أن الـ Request يتم إرسالها من جهازك إلى الـ Proxy Server وليس إلى الموقع بشكل مباشر، بعدها يقوم الـ Proxy Server بإرسال نفس الـ Request إلى سيرفر الموقع، في هذه الحالة فإن سيرفر الموقع يعرف أن الجهاز الذي طلب الصفحة هو الـ Proxy Server، وليس لديه أي معلومات عنك، عند إرجاع الاستجابة إلى الـ Proxy Server، يقوم الـ Proxy بدوره بإرجاع الاستجابة لك.
بهذه الطريقة، يفترض أن سيرفر الموقع لا يعرف الـ IP الخاص بك، كما أن مزود خدمة الإنترنت الخاص بك يرى أنك ترسل الطلب إلى الـ Proxy Server وليس إلى الموقع المحظور، كما يمكن إضافة إعدادات للـ Proxy Server بحيث يحجب الإعلانات أو المواقع ذات المحتوى غير المرغوب به بحيث لا يرجع لك الـ Response من تلك المواقع.
في الواقع قد يقوم الـ Proxy Server بتمرير بعض المعلومات عنك بما في ذلك الـ IP بتمرير هذه المعلومات عن طريق بعض الـ Headers، كما أن محتوى الطلب الخاص بك (Request Body) قد يحتوي على معلومات تدل على هويتك بشكل أو بآخر.
مفهوم الـ Reverse Proxy
الـ Reverse Proxy يعمل بشكل معاكس للـ Proxy، فبدلا من العمل كوسيط لإخفاء هوية المستخدم، فإنه يعمل كوسيط لإخفاء هوية السيرفر.
لنفترض أن الصورة السابقة تمثل زيارتك لمدونتي، المستخدم قام بإرسال Request إلى ammar.dev، الـ DNS Record الخاص بـ ammar.dev يشير إلى سيرفر الـ Reverse Proxy، يقوم سيرفر الـ Reverse Proxy بتحويل الطلب للسيرفر الأول، أو للسيرفر الثاني بحسب شروط معينة تُناقش لاحقا في المقال أثناء الكلام عن التطبيقات العملية، لنفترض أن الـ Reverse Proxy قام بتحويل الطلب إلى السيرفر الأول، سيقوم السيرفر الأول بالمعالجة ثم إرجاع الـ Respones إلى سيرفر الـ Reverse Proxy، والسيرفر سيقوم بدوره بإرجاع الاستجابة لك.
لاحظ أن جهازك لا يعرف الـ IP الخاص بالسيرفر الأول أو الثاني، هوية تلك السيرفرات مخفية تحت غطاء الـ Reverse Proxy، ويقوم الـ Reverse Proxy بتحويلك إلى السيرفر المناسب لك.
خلاصة ما سبق: الـ Proxy يعمل كوسيط بينك وبين السيرفر ويقوم بإرسال الـ Request نيابة عنك مع إخفاء بياناتك بحيث يتعرف السيرفر على الـ Proxy على أنه هو العميل (Client).
بينما الـ Reverse Proxy يأخذ منك الـ Request ويرسلها إلى السيرفر الذي يريده هو، بالتالي فإنك لا تعرف هوية السيرفر الذي قام فعليا بمعالجة البيانات الخاصة بك وارجاع الاستجابة، فأنت تتعامل فقط مع الـ Reverse Proxy.
الفوائد العملية للـ Reverse Proxy
تعرفنا على الـ Reverse Proxy كمفهوم، لكن لا بد أن الـ Reverse Proxy يحل مسائل معينة وله هدف واضح، سنستعرض عددا من الأمثلة العملية التي يفيدنا فيها استخدام الـ Reverse Proxy مع إعطاء أمثلة باستخدام Nginx.
Nginx هو Webserver لكنه يعمل أيضا كـ Reverse Proxy.
توزيع الحِمل - Load Balancing
عند تعرض موقعك لضغط عالٍ وزيارات كثيرة، ستحتاج لعمل توسع (Scaling) وإحدى طرق التوسع هي التوسع الأفقي (Horizontal scaling) وتعتمد هذه الطريقة على وجود أكثر من سيرفر يقوم بمعالجة الـ Requests.
في الصورة التي شرحنا فيها عملية إرسال الطلب عبر Reverse Proxy:
تلاحظ وجود سيرفرين، التوسع الأفقي يعتمد على زيادة عدد هذه السيرفرات بحيث يحتوي كل سيرفر على نسخة من الكود الخاص بالنظام، ويقوم الـ Reverse Proxy بتوزيع الـ Requests على هذه السيرفرات مما يخفف الضغط على السيرفر الواحد.
المثال التالي يوضح طريقة عمل Load Balancer باستخدام Nginx
1upstream app {
2 server 10.135.0.3;
3 server 10.135.0.4;
4}
5
6server {
7 server_name loadbalancer.ammar.dev;
8 listen 443 ssl;
9
10 location / {
11 proxy_pass http://app;
12 }
13
14 # إعدادات الشهادة
15 ssl_certificate /etc/ssl/fullchain.pem;
16 ssl_certificate_key /etc/ssl/privkey.pem;
17}
في المثال السابق عرفنا upstream
باسم app وهي قائمة السيرفرات التي نريد للـ Reverse Proxy الإشارة إليها، ثم تلاحظ في تعريف الـ location
نقوم باستخدام proxy_pass
للدلالة على التحويل إلى الـ upstream
.
في هذه الحالة، عند الدخول إلى رابط السيرفر سيقوم بالتحويل إلى أحد السيرفرين الذي قمنا بتعريفهما، مثال على النتيجة في الصورة المتحركة التالية:
طبعا قمت بوضع محتوى مختلف بين السيرفرين لإعطاء مثال فقط، لاحظ أنه عند كل إعادة تحميل للصفحة يتم التحويل إلى سيرفر مختلف، مما يوزع الحمل على أكثر من سيرفر.
منع الوصول المباشر للسيرفرات
كما يتضح مما سبق، الـ Reverse Proxy يُعتبر بوابة لباقي الخدمات والسيرفرات الخاصة بك، بالتالي فإن بين جميع خدماتك وسيرفراتك وبين المستخدم نقطة اتصال واحدة ألا وهي الـ Reverse Proxy Server.
في المثال السابق عندما قمنا ببناء Load Balancer بسيط، قمنا بالإشارة إلى السيرفرات التي نقوم بتوزيع الحِمل بينها باستخدام الـ Private IP على اعتبار أن هذه السيرفرات مع الـ Load Balancer موجودة على نفس الشبكة المحلية (Local Network):
1upstream app {
2 server 10.135.0.3;
3 server 10.135.0.4;
4}
يمكن إعداد هذه السيرفرات بحيث يكون لها Private IP ضمن الشبكة فقط، ولا يكون لها Public IP، وعلى هذا فيمكن للسيرفرات التواصل مع بعضها لأنها على نفس الشبكة، لكن لا يمكن لأحد من خارج الشبكة الوصول إليها بدون المرور بالـ Reverse Proxy.
لهذا السبب سيكون تركيزك الأمني على الـ Reverse Proxy Server بما أنه نقطة الاتصال الوحيدة مع العالم الخارجي.
TLS Termination
بما أن السيرفرات التي يتوزع عليها الحمل، أو سيرفرات الخدمات (Services) كلها خاصة بك، بالتالي هي موثوقة، فلا داعي لتثبيت شهادة SSL على جميع السيرفرات، بل يكفي تثبيتها على الـ Reverse Proxy لحماية المستخدم من هجمات الـ MITM أو Network Sniffing، أما التواصل ضمن الشبكة الداخلية فلا يشترط أن يكون مشفرا (Encrypted)، وهذا المفهوم يعرف بـ TLS Termination، وهذا ما تم عمله في المثال السابق الخاص بالـ Load Balancer.
Canary Deployment
الـ Canary Deployment أو الـ Canary Release هي آلية تستخدم عند وجود مزايا جديدة من النظام. مشكلة المزايا الجديدة أنها قد تكون غير مستقرة، أو ربما نكون بحاجة إلى المزيد من البيانات حول هذه الميزة قبل إطلاقها لجميع المستخدمين.
تقوم فكرة الـ Canary Deployment على إطلاق الميزة على أحد السيرفرات، وباستخدام الـ Reverse Proxy يمكننا تحويل نسبة قليلة من المستخدمين إلى هذا السيرفر، وباقي المستخدمين إلى السيرفر الذي لم يتم إطلاق الميزة فيه بعد، بهذه الطريقة يمكن لفريق البيانات في الشركة جمع البيانات المناسبة والتحقق من عدم وجود مشاكل أو اخطاء قبل تعميم النظام أو الميزة على جميع المستخدمين.
في الصورة السابقة، المستخدم يتصل بالـ Reverse Proxy كما شرحنا سابقا وليس بسيرفرات النظام مباشرة، الـ Reverse Proxy سيتحقق ما إذا كان هذا المستخدم هو من المستخدمين الذين تم تحديدهم لتجربة الميزة الجديدة (ضمن الـ 10% من المستخدمين)، وسيحول المستخدم إلى السيرفر المناسب بناء على ذلك.
مع الوقت ستتم زيادة نسبة المستخدمين الذين يتم تحويلهم إلى Canary Deployment حتى يتم في نهاية المطاف إطلاق الميزة لجميع المستخدمين.
من الأمثلة على ذلك:
- ميزة Spaces الخاصة بـ Twitter، حيث تم إصدارها لعدد قليل من المستخدمين في البداية لاختبار الميزة قبل تعميمها على الجميع
- التصاميم الجديدة للمواقع الكبيرة، أحيانا يصل تحديث التصميم على فيسبوك أو تويتر لبعض المستخدمين قبل الآخرين، وهذا بالغالب هو مثال على الـ Canary Deployment.
روابط مفيدة
http://nginx.org/en/docs/http/load_balancing.html
https://www.nginx.com/resources/glossary/reverse-proxy-server
https://www.cloudflare.com/learning/cdn/glossary/reverse-proxy