حل مشكلة ظهور عنوان IP لجميع المستخدمين على Discourse المنشَّط عبر 1Panel كـ Cloudflare بدلاً من عنوان IP الحقيقي للمتصفح

لقد قمت بتثبيت 1Panel على خادم VPS الخاص بك، وقمت بتثبيت Discourse (نشر عبر الحاويات)، واستخدمت OpenResty (نشر عبر الحاويات) كوكيل عكسي. تم استضافة النطاق عبر Cloudflare مع تفعيل CDN (السحابة الصفراء). فيما يلي دليل تشرح كيفية حل مشكلة ظهور عنوان IP للمستخدمين على أنه تابع لـ Cloudflare بدلاً من عنوان IP الحقيقي للمتصفح.

أولاً: إنشاء مهمة مجدولة في 1Panel لتنزيل أحدث قائمة عناوين IP الخاصة بـ Cloudflare أسبوعيًا وحفظها في دليل تكوين OpenResty.

  1. في القائمة الجانبية اليسرى من 1Panel، انقر على “المهام المجدولة”.

  2. انقر على زر “إنشاء مهمة مجدولة” في الزاوية العلوية اليمنى.

  3. املأ المعلمات التالية (يمكنك نسخها ولصقها مباشرة):

  • نوع المهمة: اختر نص برمجي Shell.

  • اسم المهمة: على سبيل المثال تحديث تلقائي لشبكات عناوين IP الخاصة بـ Cloudflare.

  • دورة التنفيذ: يُوصى باختيار أسبوعيًا (مثل يوم السبت الساعة 03:00 صباحًا).

  • محتوى النص البرمجي: انسخ النص البرمجي الكامل أدناه والصقه مباشرة (ملاحظة: يرجى تعديل اسم الحاوية ومسار دليل التكوين في أعلى النص البرمجي أولاً):

#!/bin/bash
# منطقة التكوين
CONTAINER_NAME="اسم حاوية openresty في 1Panel"
# قم بتعديلها لتتوافق مع دليل proxy للموقع المحدد
CONF_DIR="/opt/1panel/www/sites/www.نطاق_موقعك/proxy"

echo "[$(date)] بدء سحب أحدث شبكات عناوين IP من Cloudflare الرسمية..."
TEMP_DIR=$(mktemp -d)

# سحب قائمة عناوين IP وتحويلها إلى تنسيق يفهمه Nginx
curl -fsS https://www.cloudflare.com/ips-v4 | sed 's/.*/set_real_ip_from \&;/' > $TEMP_DIR/cf-ips-v4.conf
curl -fsS https://www.cloudflare.com/ips-v6 | sed 's/.*/set_real_ip_from \&;/' > $TEMP_DIR/cf-ips-v6.conf

# التحقق من الملفات ونقلها
if [[ -s $TEMP_DIR/cf-ips-v4.conf ]] && [[ -s $TEMP_DIR/cf-ips-v6.conf ]]; then
    mv $TEMP_DIR/cf-ips-v4.conf $CONF_DIR/
    mv $TEMP_DIR/cf-ips-v6.conf $CONF_DIR/
    echo "[$(date)] تم تحديث ملفات التكوين بنجاح إلى $CONF_DIR."
else
    echo "[$(date)] خطأ: فشل سحب عناوين IP الخاصة بـ Cloudflare!"
    rm -rf $TEMP_DIR
    exit 1
fi
rm -rf $TEMP_DIR

# اختبار وإعادة تحميل Nginx
echo "[$(date)] جاري اختبار تكوين Nginx..."
if docker exec $CONTAINER_NAME nginx -t; then
    docker exec $CONTAINER_NAME nginx -s reload
    echo "[$(date)] نجاح! تم إعادة تحميل تكوين OpenResty بنجاح."
else
    echo "[$(date)] فشل! اختبار تكوين Nginx لم ينجح."
    exit 1
fi

بعد إنشاء المهمة، لا داعي للانتظار حتى يوم السبت؛ يمكنك اختبارها فورًا: ابحث عن المهمة التي أنشأتها للتو في قائمة “المهام المجدولة”.

انقر على زر “التقرير” على الجانب الأيمن. راجع نافذة السجلات التي تظهر. إذا أظهرت آخر بضعة أسطر نجاح! تم إعادة تحميل تكوين OpenResty بنجاح، فهذا يعني أن العملية بأكملها تعمل بشكل مثالي داخل 1Panel!

ثانياً: إضافة تكوين realip في OpenResty

قم بإنشاء ملف جديد في دليل المضيف /opt/1panel/www/sites/www.نطاق_موقعك/proxy/ (اسم الملف اختياري، بشرط أن ينتهي بـ .conf، وسيتم تحميله تلقائيًا من خلال include *.conf في التكوين الرئيسي): realip.conf

real_ip_header CF-Connecting-IP;
real_ip_recursive on;

ثالثاً: إعادة تحميل OpenResty

docker exec اسم_حاوية_openresty_في_1Panel nginx -t
docker exec اسم_حاوية_openresty_في_1Panel nginx -s reload

رابعاً: التحقق مما إذا حصل OpenResty على عنوان IP الحقيقي

راجع سجل الوصول (access log) الخاص بـ OpenResty:

tail -f /opt/1panel/www/sites/www.نطاق_موقعك/log/access.log

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

خامساً: توضيحات جانبية بخصوص Discourse

إضافة - "templates/cloudflare.template.yml" في ملف app.yml الخاص بـ Discourse تكون فعالة فقط عندما يكون Discourse متصلاً مباشرة بـ Cloudflare. نظرًا لإضافة وكيل عكسي OpenResty في المنتصف، فإن عنوان IP المصدر الذي تراه حاوية Discourse هو في الواقع بوابة Docker (مثل 172.17.0.1 أو 172.18.0.1)، لذا لن تتطابق set_real_ip_from <CloudflareIP> الموجودة في هذا القالب.

ولكن طالما قمت باستعادة عنوان IP الحقيقي على مستوى OpenResty حسب الخطوات المذكورة أعلاه، وقمت بنقل X-Forwarded-For نظيف، فستتمكن Rails في الخلفية الخاصة بـ Discourse من تحديد عنوان IP الحقيقي للمستخدم بشكل صحيح، لأن Rails تثق افتراضيًا في شبكات Docker الخاصة مثل 172.x.x.x.

لذلك، لا حاجة لإضافة - "templates/cloudflare.template.yml" في ملف app.yml الخاص بـ Discourse.