أنس أسامة
عضو متفاعل
معلومات أنس أسامة
- المشاركات
- 111
- المعدل اليومي
- 0.05
- مستوى التفاعل
- 6
- قوة السمعه
أوسمة العضو
سلام عليكم جميعا
ان الي حدث في هيلبرنت حدث لي ايضا في منتداي اذا تفاجأت عدد كبير من الزوار في منتداي يشكل غير طبيعي قلت انها يمكن بعد تغير الاستايل حدث ذلك لكن الصدمة اذا وجدت هجوم قوي متعمد لايقاف المنتدي بشكل مرهق جدا لم انام مرتاح بسبب عدد الزوار
طبعا وجدت الذكاء الاصناعي يمكن اعرف سبب لك
الي قال له لي انك تتعرض لهجوم متعمد من 4 اي بي تجعل تراكم زوار بسبب ذلك
اولا قم بحظر الاي بي
ثم قمت تعديل ملف الهات اكسس
ثم قمت تعديل بسيط في جدول سيزون
2. الحل الجذري (تغيير نوع الجدول إلى MyISAM)
كود🔒 يجب تسجيل الدخول لمشاهدة محتوى الكود.
4. حظر البوتات الوهمية عبر ملف .htaccess
بعد ذلك عدلت علي قالب وضعت كود لتنظيف الجدول تلقائي
بعد جربت وانتهت المعاناه الي تسببت في تعطيل بعض المواقع المهمة
تحياتي للجميع
وعليكم السلام ورحمة الله وبركاته
أخي الكريم، مع احترامي لتجربتك، أنا لا أوافقك على الخطوات بهذه الصورة، وخصوصًا اعتبار تحويل جدول `session` إلى `MyISAM` هو «الحل الجذري». هناك خلط بين علاج نتيجة الضغط وبين علاج مصدر المشكلة نفسه
الموضوع يحتاج معالجة على عدة مستويات: Cloudflare أو الـFirewall، ثم Web Server، ثم PHP، ثم قاعدة البيانات، وأخيرًا جداول الجلسات في vBulletin أو XenForo
أول نقطة: لا يكفي أن يقول الذكاء الاصطناعي إن الهجوم قادم من 4 IPs. هذا يجب إثباته من Access Logs في السيرفر ومعرفة:
* عدد الطلبات من كل IP
* عدد الطلبات في الثانية أو الدقيقة
* أكثر الصفحات التي يتم طلبها
* الـUser-Agent
* هل الـIP يحافظ على Cookies أم ينشئ Session جديدة باستمرار
* هل الطلبات حقيقية أم Bots أو Crawlers
* هل الـIPs ثابتة أم تتغير باستمرار
لأن ارتفاع رقم «المتواجدين الآن» وحده لا يثبت وجود DDoS. أربعة IPs مثلًا يمكنها إنشاء آلاف الجلسات إذا كانت ترسل آلاف الطلبات ولا تحتفظ بالـCookie، وفي المقابل قد ترى آلاف الزوار الشرعيين بدون أن تكون هناك مشكلة
أما إذا أثبتت السجلات فعلًا أن 4 IPs ترسل عددًا هائلًا من الطلبات، فالحظر الصحيح يبدأ من أعلى مستوى ممكن، وليس من قاعدة البيانات
إذا كان لديك وصول Root، يتم حظر الـIPs من Firewall مثل CSF/Firewalld/nftables قبل أن تصل إلى Apache أو LiteSpeed أو PHP أو MySQL
أما حظرها في `.htaccess` فهو مفيد كطبقة إضافية، لكنه ليس أفضل مكان لإيقاف هجوم؛ لأن الطلب وصل بالفعل إلى Web Server
يمكن مثلًا في Apache/LiteSpeed إضافة:
apache
RewriteEngine On
RewriteCond %{REMOTE_ADDR} ^1\.2\.3\.4$ [OR]
RewriteCond %{ %{REMOTE_ADDR} ^5\.6\.7\.8$ [OR]
RewriteCond %{REMOTE_ADDR} ^9\.10\.11\.12$ [OR]
RewriteCond %{REMOTE_ADDR} ^13\.14\.15\.16$
RewriteRule ^ - [F,L]
طبعًا يتم استبدال العناوين بالـIPs الحقيقية التي ثبت من Logs أنها مصدر الهجوم
ولكن إذا كان الهجوم موزعًا ويستخدم مئات أو آلاف الـIPs، فإضافة IP وراء IP إلى `.htaccess` ليست حلًا
هنا يأتي دور Firewall وRate Limiting وWAF
إذا كان الموقع يستخدم Cloudflare، فأنا أفضل أن يكون الحل على النحو التالي:
1. تفعيل Proxy البرتقالي على سجلات الموقع
2. استخدام WAF Custom Rules لحظر الـIPs المثبت أنها مهاجمة
مثال:
ip.src in {1.2.3.4 5.6.7.8 9.10.11.12}
والإجراء:
Block
3. إذا كانت الـIPs كثيرة أو متغيرة، نستخدم Rate Limiting بدل مطاردتها واحدة واحدة
يتم تحديد عدد طبيعي من الطلبات حسب حركة المنتدى الفعلية، وأي IP يتجاوز المعدل بصورة غير طبيعية يأخذ:
Managed Challenge
وفي حالة التأكد بأنه Traffic ضار يمكن الانتقال إلى:
Block
ولا أنصح بوضع رقم Rate Limit عشوائي يصلح لكل المنتديات؛ منتدى لديه 50 مستخدمًا يختلف تمامًا عن منتدى عليه عشرات آلاف الزوار
Cloudflare نفسه ينصح بمراقبة Security Events أولًا وضبط الـthreshold حسب الحركة الحقيقية
4. تفعيل Bot Fight Mode أو Super Bot Fight Mode حسب الخطة، مع مراقبة أي False Positives
5. عدم حظر Verified Bots الشرعية مثل Google بشكل عشوائي لأننا لا نريد معالجة الهجوم على حساب الأرشفة
6. أثناء هجوم Layer 7 قوي جدًا يمكن استخدام Managed Challenge بصورة أشد مؤقتًا، أو وضع الحماية المشددة المناسبة حتى ينتهي الهجوم
7. من المهم جدًا أيضًا حماية Origin IP. إذا كان Cloudflare أمام الموقع ولكن المهاجم يعرف IP السيرفر ويستطيع الاتصال به مباشرة، يمكنه تجاوز Cloudflare بالكامل
في إعداد احترافي، يسمح Firewall للـHTTP/HTTPS بالوصول إلى Origin من شبكات Cloudflare فقط، مع إبقاء الخدمات الإدارية المطلوبة منفصلة
وعند استخدام Cloudflare يجب ضبط استعادة الـReal Visitor IP في Apache/LiteSpeed بصورة صحيحة، وإلا قد تظهر IPs الخاصة بـCloudflare في Logs وFail2Ban بدل IP الحقيقي للزائر
وهذه نقطة Cloudflare نفسه يحذر منها
بعد ذلك نصل إلى قاعدة البيانات، وهنا تحديدًا لا أوافق على تحويل `session` إلى `MyISAM` كحل جذري
بالنسبة إلى vBulletin، خصوصًا الإصدارات القديمة مثل vB3/vB4، يجب أولًا معرفة المحرك الحالي:
sql
SELECT
TABLE_NAME,
ENGINE,
TABLE_ROWS,
DATA_LENGTH,
INDEX_LENGTH
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME LIKE '%session%';
إذا كان جدول:
session
يستخدم:
MEMORY
فهذا يفسر كثيرًا من حالات:
The table 'session' is full
لأن جدول MEMORY له حدود مرتبطة بذاكرة MySQL و`max_heap_table_size`
وهنا أرى أن الحل الأفضل للمنتديات الكبيرة هو:
sql
ALTER TABLE `session` ENGINE=InnoDB;
```
وإذا كان هناك Prefix مثل:
vb_session
يكون:
sql
ALTER TABLE `vb_session` ENGINE=InnoDB;
```
وليس:
sql
ALTER TABLE `session` ENGINE=MyISAM;
```
والسبب تقني
`MyISAM` يعتمد أساسًا على Table-Level Locking
بينما `InnoDB` مصمم بصورة أفضل للقراءة والكتابة المتزامنة ويستخدم Row-Level Locking في الحالات المناسبة
وجدول `session` من أكثر الجداول تعرضًا للكتابة والتحديث عندما يكون هناك آلاف الزوار والطلبات في نفس اللحظة
لذلك تحت الضغط العالي لا أرى منطقيًا أن نحول جدولًا شديد النشاط إلى MyISAM ونعتبر ذلك حلًا جذريًا
بل حتى الدعم الرسمي لـvBulletin ناقش مشكلة امتلاء `session` في vBulletin 4، وذكر أن الجدول كان MEMORY وأن تحويله إلى InnoDB قد يحل المشكلة، وأن InnoDB أصبح الخيار الأنسب مع MySQL الحديث:
https://forum.vbulletin.com/forum/v...hooting/4427432-what-are-normal-guest-numbers
هناك نقطة مهمة أيضًا:
`InnoDB` لا يقوم بنفسه بحذف Sessions القديمة بطريقة سحرية
البرنامج نفسه لديه آليات للتعامل مع الجلسات المنتهية. الفارق أن جدول MEMORY يمكن أن يصطدم بحده بسرعة أثناء الطفرة، بينما نقل الجدول إلى InnoDB يزيل هذا الاختناق ويعطي تحملًا أفضل كثيرًا
إذا توقف المنتدى بالفعل بسبب امتلاء `session` وكان المطلوب إنقاذه فورًا، يمكن في حالة الطوارئ وبعد فهم أثر العملية تفريغ جلسات المنتدى:
sql
TRUNCATE TABLE `session`;
ثم:
sql
ALTER TABLE `session` ENGINE=InnoDB;
لكن `TRUNCATE` ليس عملية تحسين دورية ولا أنصح بتشغيلها كل ساعة أو كل يوم. هي إجراء إنقاذ إذا كان جدول الجلسات نفسه هو الذي أوقف المنتدى، لأنها تمسح الجلسات الحالية وتجبرها على إعادة الإنشاء
ولا علاقة لجدول `cpsession` بضغط الزوار العادي؛ لذلك لا داعي للعبث بجلسات لوحة الإدارة بسبب هجوم على صفحات المنتدى
أما XenForo فهناك نقطة مهمة جدًا يغفل عنها البعض
في الإصدارات القديمة من XenForo كانت بعض جداول الجلسات تستخدم MyISAM أو MEMORY
مثلًا في XF 2.2 كان من الطبيعي أن نجد:
xf_session = MyISAM
xf_session_activity = MEMORY
ولكن ابتداءً من XenForo 2.3 تغير الاتجاه رسميًا
مطوّر XenForo Chris D أعلن أن XenForo 2.3 أصبح يحول الجداول المتبقية إلى InnoDB، وأن التثبيتات الجديدة تستخدم InnoDB افتراضيًا، وعندما سُئل تحديدًا عن جداول MEMORY أكد أنها أصبحت InnoDB أيضًا:
https://xenforo.com/community/threads/miscellaneous-changes-for-xenforo-2-3.217243/
لذلك في XenForo 2.3 يجب أولًا فحص المحركات:
sql
SELECT
TABLE_NAME,
ENGINE,
TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME IN (
'xf_session',
'xf_session_activity',
'xf_session_admin'
);
إذا كانت نسخة XF 2.3 تمت ترقيتها من إصدار قديم وما زال مثلًا:
xf_session_activity = MEMORY
فيجب أولًا التأكد أن الترقية اكتملت بصورة صحيحة
أما في منتدى كبير يعاني فعلًا من ضغط على هذه الجداول، وبعد Backup، فإن تحويل جداول الجلسات القديمة إلى InnoDB يصبح منطقيًا:
sql
ALTER TABLE `xf_session` ENGINE=InnoDB;
ALTER TABLE `xf_session_activity` ENGINE=InnoDB;
```
وخاصة أن هذا الاتجاه أصبح هو نفسه اتجاه XenForo 2.3
أما في XenForo 2.2 وما قبله، فالأفضل أصلًا الترقية إلى إصدار حديث، وإذا تعذرت الترقية فلا يتم تحويل كل جداول قاعدة البيانات عشوائيًا؛ نحدد الجدول المسبب للمشكلة ونقرر بناءً على الإصدار وحالة السيرفر
هناك حل إضافي مهم جدًا في XenForo للمواقع الكبيرة وهو Redis
XenForo يدعم رسميًا تخزين Sessions في Cache:
php
$config['cache']['enabled'] = true;
$config['cache']['provider'] = 'Redis';
$config['cache']['config'] = [
'host' => '127.0.0.1',
'port' => 6379
];
$config['cache']['sessions'] = true;
وهذا يقلل الضغط على قاعدة البيانات بصورة كبيرة عند وجود عدد ضخم من الجلسات، بشرط أن يكون Redis مضبوطًا بصورة صحيحة ولديه ذاكرة كافية
XenForo يوثق ذلك رسميًا:
https://docs.xenforo.com/manual/config/cache
ويوجد أيضًا Guest Page Cache في XenForo، وهو مفيد جدًا إذا كان القسم الأكبر من الضغط من الزوار غير المسجلين، لأن الهدف الحقيقي ليس فقط منع جدول `session` من الامتلاء وإنما تقليل عدد المرات التي يحتاج فيها كل طلب إلى تشغيل PHP وتنفيذ استعلامات MySQL من الأساس
وعلى مستوى MySQL/MariaDB لا يكفي أيضًا أن نقول "حوّل الجدول وانتهى"
يجب فحص:
sql
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'max_heap_table_size';
SHOW VARIABLES LIKE 'tmp_table_size';
وكذلك:
sql
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Threads_running';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
```
إذا اعتمدنا على InnoDB بينما `innodb_buffer_pool_size` صغير جدًا بالنسبة لحجم قاعدة البيانات والذاكرة المتاحة، فنحن لم نضبط السيرفر بشكل صحيح
وبالمقابل لا أنصح برفع:
max_connections
إلى أرقام ضخمة عشوائيًا، لأن ذلك أحيانًا يجعل السيرفر يسقط أسرع أثناء الهجوم بدل أن يحميه
الخلاصة:
أنا لا أوافق على أن الحل يكون:
هجوم
↓
حظر 4 IP
↓
تعديل htaccess
↓
تحويل session إلى MyISAM
↓
انتهت المشكلة
هذا ليس حلًا جذريًا
الحل الصحيح يكون:
تأكيد الهجوم من Access Logs
↓
معرفة IPs + URLs + Request Rate + User Agents
↓
Cloudflare/WAF أو Firewall
↓
Rate Limiting للبوتات والطلبات غير الطبيعية
↓
منع الوصول المباشر إلى Origin عند استخدام Cloudflare
↓
ضبط Apache/LiteSpeed/Nginx
↓
منع الطلب الضار قبل وصوله إلى PHP
↓
ضبط MySQL/MariaDB
↓
استخدام InnoDB لجداول الجلسات المناسبة
↓
Redis/Cache عند الحاجة
↓
مراقبة Logs وCPU وRAM وI/O وMySQL Threads
وأهم شيء: تغيير `session` إلى InnoDB يعالج اختناقًا مهمًا جدًا في قاعدة البيانات، لكنه لا يوقف المهاجم نفسه
والعكس صحيح أيضًا: حظر IP واحد لا يعالج مشكلة تصميم قاعدة البيانات إذا كان جدول الجلسات غير قادر أصلًا على تحمل الزيارات الكبيرة
الحماية الصحيحة هي أن نعالج الاثنين معًا
لذلك أختلف معك تحديدًا في وصف:
sql
ALTER TABLE session ENGINE=MyISAM;
بأنه «الحل الجذري»
في بيئة منتدى حديثة وعالية الضغط، أفضّل InnoDB لجداول الجلسات التي تسبب هذا الاختناق، مع Firewall/WAF وRate Limiting قبل التطبيق. وهذا ليس مجرد رأي؛ MySQL نفسه يوضح الفرق في آلية locking، وvBulletin ناقش رسميًا تحويل session إلى InnoDB، وXenForo نفسه اتجه في 2.3 إلى InnoDB للجداول التي كانت سابقًا MEMORY/MyISAM
أما الحل الجذري الحقيقي للهجوم فهو منع أكبر قدر ممكن من الطلبات الضارة قبل وصولها أصلًا إلى PHP وقاعدة البيانات، ثم جعل التطبيق وقاعدة البيانات قادرين على تحمل ما يصل إليهما من زيارات شرعية
أخي الكريم، مع احترامي لتجربتك، أنا لا أوافقك على الخطوات بهذه الصورة، وخصوصًا اعتبار تحويل جدول `session` إلى `MyISAM` هو «الحل الجذري». هناك خلط بين علاج نتيجة الضغط وبين علاج مصدر المشكلة نفسه
الموضوع يحتاج معالجة على عدة مستويات: Cloudflare أو الـFirewall، ثم Web Server، ثم PHP، ثم قاعدة البيانات، وأخيرًا جداول الجلسات في vBulletin أو XenForo
أول نقطة: لا يكفي أن يقول الذكاء الاصطناعي إن الهجوم قادم من 4 IPs. هذا يجب إثباته من Access Logs في السيرفر ومعرفة:
* عدد الطلبات من كل IP
* عدد الطلبات في الثانية أو الدقيقة
* أكثر الصفحات التي يتم طلبها
* الـUser-Agent
* هل الـIP يحافظ على Cookies أم ينشئ Session جديدة باستمرار
* هل الطلبات حقيقية أم Bots أو Crawlers
* هل الـIPs ثابتة أم تتغير باستمرار
لأن ارتفاع رقم «المتواجدين الآن» وحده لا يثبت وجود DDoS. أربعة IPs مثلًا يمكنها إنشاء آلاف الجلسات إذا كانت ترسل آلاف الطلبات ولا تحتفظ بالـCookie، وفي المقابل قد ترى آلاف الزوار الشرعيين بدون أن تكون هناك مشكلة
أما إذا أثبتت السجلات فعلًا أن 4 IPs ترسل عددًا هائلًا من الطلبات، فالحظر الصحيح يبدأ من أعلى مستوى ممكن، وليس من قاعدة البيانات
إذا كان لديك وصول Root، يتم حظر الـIPs من Firewall مثل CSF/Firewalld/nftables قبل أن تصل إلى Apache أو LiteSpeed أو PHP أو MySQL
أما حظرها في `.htaccess` فهو مفيد كطبقة إضافية، لكنه ليس أفضل مكان لإيقاف هجوم؛ لأن الطلب وصل بالفعل إلى Web Server
يمكن مثلًا في Apache/LiteSpeed إضافة:
apache
RewriteEngine On
RewriteCond %{REMOTE_ADDR} ^1\.2\.3\.4$ [OR]
RewriteCond %{ %{REMOTE_ADDR} ^5\.6\.7\.8$ [OR]
RewriteCond %{REMOTE_ADDR} ^9\.10\.11\.12$ [OR]
RewriteCond %{REMOTE_ADDR} ^13\.14\.15\.16$
RewriteRule ^ - [F,L]
طبعًا يتم استبدال العناوين بالـIPs الحقيقية التي ثبت من Logs أنها مصدر الهجوم
ولكن إذا كان الهجوم موزعًا ويستخدم مئات أو آلاف الـIPs، فإضافة IP وراء IP إلى `.htaccess` ليست حلًا
هنا يأتي دور Firewall وRate Limiting وWAF
إذا كان الموقع يستخدم Cloudflare، فأنا أفضل أن يكون الحل على النحو التالي:
1. تفعيل Proxy البرتقالي على سجلات الموقع
2. استخدام WAF Custom Rules لحظر الـIPs المثبت أنها مهاجمة
مثال:
ip.src in {1.2.3.4 5.6.7.8 9.10.11.12}
والإجراء:
Block
3. إذا كانت الـIPs كثيرة أو متغيرة، نستخدم Rate Limiting بدل مطاردتها واحدة واحدة
يتم تحديد عدد طبيعي من الطلبات حسب حركة المنتدى الفعلية، وأي IP يتجاوز المعدل بصورة غير طبيعية يأخذ:
Managed Challenge
وفي حالة التأكد بأنه Traffic ضار يمكن الانتقال إلى:
Block
ولا أنصح بوضع رقم Rate Limit عشوائي يصلح لكل المنتديات؛ منتدى لديه 50 مستخدمًا يختلف تمامًا عن منتدى عليه عشرات آلاف الزوار
Cloudflare نفسه ينصح بمراقبة Security Events أولًا وضبط الـthreshold حسب الحركة الحقيقية
4. تفعيل Bot Fight Mode أو Super Bot Fight Mode حسب الخطة، مع مراقبة أي False Positives
5. عدم حظر Verified Bots الشرعية مثل Google بشكل عشوائي لأننا لا نريد معالجة الهجوم على حساب الأرشفة
6. أثناء هجوم Layer 7 قوي جدًا يمكن استخدام Managed Challenge بصورة أشد مؤقتًا، أو وضع الحماية المشددة المناسبة حتى ينتهي الهجوم
7. من المهم جدًا أيضًا حماية Origin IP. إذا كان Cloudflare أمام الموقع ولكن المهاجم يعرف IP السيرفر ويستطيع الاتصال به مباشرة، يمكنه تجاوز Cloudflare بالكامل
في إعداد احترافي، يسمح Firewall للـHTTP/HTTPS بالوصول إلى Origin من شبكات Cloudflare فقط، مع إبقاء الخدمات الإدارية المطلوبة منفصلة
وعند استخدام Cloudflare يجب ضبط استعادة الـReal Visitor IP في Apache/LiteSpeed بصورة صحيحة، وإلا قد تظهر IPs الخاصة بـCloudflare في Logs وFail2Ban بدل IP الحقيقي للزائر
وهذه نقطة Cloudflare نفسه يحذر منها
بعد ذلك نصل إلى قاعدة البيانات، وهنا تحديدًا لا أوافق على تحويل `session` إلى `MyISAM` كحل جذري
بالنسبة إلى vBulletin، خصوصًا الإصدارات القديمة مثل vB3/vB4، يجب أولًا معرفة المحرك الحالي:
sql
SELECT
TABLE_NAME,
ENGINE,
TABLE_ROWS,
DATA_LENGTH,
INDEX_LENGTH
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME LIKE '%session%';
إذا كان جدول:
session
يستخدم:
MEMORY
فهذا يفسر كثيرًا من حالات:
The table 'session' is full
لأن جدول MEMORY له حدود مرتبطة بذاكرة MySQL و`max_heap_table_size`
وهنا أرى أن الحل الأفضل للمنتديات الكبيرة هو:
sql
ALTER TABLE `session` ENGINE=InnoDB;
```
وإذا كان هناك Prefix مثل:
vb_session
يكون:
sql
ALTER TABLE `vb_session` ENGINE=InnoDB;
```
وليس:
sql
ALTER TABLE `session` ENGINE=MyISAM;
```
والسبب تقني
`MyISAM` يعتمد أساسًا على Table-Level Locking
بينما `InnoDB` مصمم بصورة أفضل للقراءة والكتابة المتزامنة ويستخدم Row-Level Locking في الحالات المناسبة
وجدول `session` من أكثر الجداول تعرضًا للكتابة والتحديث عندما يكون هناك آلاف الزوار والطلبات في نفس اللحظة
لذلك تحت الضغط العالي لا أرى منطقيًا أن نحول جدولًا شديد النشاط إلى MyISAM ونعتبر ذلك حلًا جذريًا
بل حتى الدعم الرسمي لـvBulletin ناقش مشكلة امتلاء `session` في vBulletin 4، وذكر أن الجدول كان MEMORY وأن تحويله إلى InnoDB قد يحل المشكلة، وأن InnoDB أصبح الخيار الأنسب مع MySQL الحديث:
https://forum.vbulletin.com/forum/v...hooting/4427432-what-are-normal-guest-numbers
هناك نقطة مهمة أيضًا:
`InnoDB` لا يقوم بنفسه بحذف Sessions القديمة بطريقة سحرية
البرنامج نفسه لديه آليات للتعامل مع الجلسات المنتهية. الفارق أن جدول MEMORY يمكن أن يصطدم بحده بسرعة أثناء الطفرة، بينما نقل الجدول إلى InnoDB يزيل هذا الاختناق ويعطي تحملًا أفضل كثيرًا
إذا توقف المنتدى بالفعل بسبب امتلاء `session` وكان المطلوب إنقاذه فورًا، يمكن في حالة الطوارئ وبعد فهم أثر العملية تفريغ جلسات المنتدى:
sql
TRUNCATE TABLE `session`;
ثم:
sql
ALTER TABLE `session` ENGINE=InnoDB;
لكن `TRUNCATE` ليس عملية تحسين دورية ولا أنصح بتشغيلها كل ساعة أو كل يوم. هي إجراء إنقاذ إذا كان جدول الجلسات نفسه هو الذي أوقف المنتدى، لأنها تمسح الجلسات الحالية وتجبرها على إعادة الإنشاء
ولا علاقة لجدول `cpsession` بضغط الزوار العادي؛ لذلك لا داعي للعبث بجلسات لوحة الإدارة بسبب هجوم على صفحات المنتدى
أما XenForo فهناك نقطة مهمة جدًا يغفل عنها البعض
في الإصدارات القديمة من XenForo كانت بعض جداول الجلسات تستخدم MyISAM أو MEMORY
مثلًا في XF 2.2 كان من الطبيعي أن نجد:
xf_session = MyISAM
xf_session_activity = MEMORY
ولكن ابتداءً من XenForo 2.3 تغير الاتجاه رسميًا
مطوّر XenForo Chris D أعلن أن XenForo 2.3 أصبح يحول الجداول المتبقية إلى InnoDB، وأن التثبيتات الجديدة تستخدم InnoDB افتراضيًا، وعندما سُئل تحديدًا عن جداول MEMORY أكد أنها أصبحت InnoDB أيضًا:
https://xenforo.com/community/threads/miscellaneous-changes-for-xenforo-2-3.217243/
لذلك في XenForo 2.3 يجب أولًا فحص المحركات:
sql
SELECT
TABLE_NAME,
ENGINE,
TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME IN (
'xf_session',
'xf_session_activity',
'xf_session_admin'
);
إذا كانت نسخة XF 2.3 تمت ترقيتها من إصدار قديم وما زال مثلًا:
xf_session_activity = MEMORY
فيجب أولًا التأكد أن الترقية اكتملت بصورة صحيحة
أما في منتدى كبير يعاني فعلًا من ضغط على هذه الجداول، وبعد Backup، فإن تحويل جداول الجلسات القديمة إلى InnoDB يصبح منطقيًا:
sql
ALTER TABLE `xf_session` ENGINE=InnoDB;
ALTER TABLE `xf_session_activity` ENGINE=InnoDB;
```
وخاصة أن هذا الاتجاه أصبح هو نفسه اتجاه XenForo 2.3
أما في XenForo 2.2 وما قبله، فالأفضل أصلًا الترقية إلى إصدار حديث، وإذا تعذرت الترقية فلا يتم تحويل كل جداول قاعدة البيانات عشوائيًا؛ نحدد الجدول المسبب للمشكلة ونقرر بناءً على الإصدار وحالة السيرفر
هناك حل إضافي مهم جدًا في XenForo للمواقع الكبيرة وهو Redis
XenForo يدعم رسميًا تخزين Sessions في Cache:
php
$config['cache']['enabled'] = true;
$config['cache']['provider'] = 'Redis';
$config['cache']['config'] = [
'host' => '127.0.0.1',
'port' => 6379
];
$config['cache']['sessions'] = true;
وهذا يقلل الضغط على قاعدة البيانات بصورة كبيرة عند وجود عدد ضخم من الجلسات، بشرط أن يكون Redis مضبوطًا بصورة صحيحة ولديه ذاكرة كافية
XenForo يوثق ذلك رسميًا:
https://docs.xenforo.com/manual/config/cache
ويوجد أيضًا Guest Page Cache في XenForo، وهو مفيد جدًا إذا كان القسم الأكبر من الضغط من الزوار غير المسجلين، لأن الهدف الحقيقي ليس فقط منع جدول `session` من الامتلاء وإنما تقليل عدد المرات التي يحتاج فيها كل طلب إلى تشغيل PHP وتنفيذ استعلامات MySQL من الأساس
وعلى مستوى MySQL/MariaDB لا يكفي أيضًا أن نقول "حوّل الجدول وانتهى"
يجب فحص:
sql
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'max_heap_table_size';
SHOW VARIABLES LIKE 'tmp_table_size';
وكذلك:
sql
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Threads_running';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
```
إذا اعتمدنا على InnoDB بينما `innodb_buffer_pool_size` صغير جدًا بالنسبة لحجم قاعدة البيانات والذاكرة المتاحة، فنحن لم نضبط السيرفر بشكل صحيح
وبالمقابل لا أنصح برفع:
max_connections
إلى أرقام ضخمة عشوائيًا، لأن ذلك أحيانًا يجعل السيرفر يسقط أسرع أثناء الهجوم بدل أن يحميه
الخلاصة:
أنا لا أوافق على أن الحل يكون:
هجوم
↓
حظر 4 IP
↓
تعديل htaccess
↓
تحويل session إلى MyISAM
↓
انتهت المشكلة
هذا ليس حلًا جذريًا
الحل الصحيح يكون:
تأكيد الهجوم من Access Logs
↓
معرفة IPs + URLs + Request Rate + User Agents
↓
Cloudflare/WAF أو Firewall
↓
Rate Limiting للبوتات والطلبات غير الطبيعية
↓
منع الوصول المباشر إلى Origin عند استخدام Cloudflare
↓
ضبط Apache/LiteSpeed/Nginx
↓
منع الطلب الضار قبل وصوله إلى PHP
↓
ضبط MySQL/MariaDB
↓
استخدام InnoDB لجداول الجلسات المناسبة
↓
Redis/Cache عند الحاجة
↓
مراقبة Logs وCPU وRAM وI/O وMySQL Threads
وأهم شيء: تغيير `session` إلى InnoDB يعالج اختناقًا مهمًا جدًا في قاعدة البيانات، لكنه لا يوقف المهاجم نفسه
والعكس صحيح أيضًا: حظر IP واحد لا يعالج مشكلة تصميم قاعدة البيانات إذا كان جدول الجلسات غير قادر أصلًا على تحمل الزيارات الكبيرة
الحماية الصحيحة هي أن نعالج الاثنين معًا
لذلك أختلف معك تحديدًا في وصف:
sql
ALTER TABLE session ENGINE=MyISAM;
بأنه «الحل الجذري»
في بيئة منتدى حديثة وعالية الضغط، أفضّل InnoDB لجداول الجلسات التي تسبب هذا الاختناق، مع Firewall/WAF وRate Limiting قبل التطبيق. وهذا ليس مجرد رأي؛ MySQL نفسه يوضح الفرق في آلية locking، وvBulletin ناقش رسميًا تحويل session إلى InnoDB، وXenForo نفسه اتجه في 2.3 إلى InnoDB للجداول التي كانت سابقًا MEMORY/MyISAM
أما الحل الجذري الحقيقي للهجوم فهو منع أكبر قدر ممكن من الطلبات الضارة قبل وصولها أصلًا إلى PHP وقاعدة البيانات، ثم جعل التطبيق وقاعدة البيانات قادرين على تحمل ما يصل إليهما من زيارات شرعية