برنامه نویسی

شرلوک هلمز: مورد اضافه بار ردیس در طول یک حمله DDoS

روز آرامی بود تا اینکه فاجعه رخ داد. ما هشدارهایی در مورد حملات DDoS و brute-force دریافت کردیم که از IP های ربات تصادفی منشا می گرفتند. تیم ما به سرعت بسیج شد تا حملات را کاهش دهد. درست زمانی که فکر می کردیم اوضاع تحت کنترل است، پیام هشداردهنده دیگری ظاهر شد: پایگاه داده Redis ما در دسترس بود ظرفیت 80 درصد! با توجه به اینکه Redis DB ما معمولاً کمتر از 20 مگابایت باقی می‌ماند، این به ویژه تکان‌دهنده بود.

مرحله تحقیق: رمز و راز ردیس

giphy

قبل از پرداختن به مشکل Redis، ما بر توقف حملات DDoS و brute-force تمرکز کردیم. ما محدودیت نرخ را برای نقاط پایانی خاص از طریق Cloudflare اجرا کردیم.

اکنون، بیایید آنچه را که در Redis ذخیره می کنیم را بررسی کنیم. ما از آن برای مدیریت جلسات کاربر در برنامه Node.js خود با Passport.js استفاده می کنیم. در اینجا نمونه ای از ظاهر یک جلسه آمده است:

{
  "cookie": {
    "originalMaxAge": number,
    "expires": "date",
    "secure": true,
    "httpOnly": false,
    "domain": "domain",
    "path": "https://dev.to/",
    "sameSite": false
  },
  "passport": { 
    "user": // Actual user data here
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با این شرایط، ما تحقیقات خود را آغاز کردیم. من تمام داده ها را در Redis جستجو کردم تا اعتبار جلسات را بررسی کنم. در کمال تعجب، فقط 10% از جلسات حاوی داده های کاربر معتبر بود. بقیه نامعتبر بودند، فاقد آن بودند کاربر کلید

کد معرفی شده: چرا تعداد جلسات نامعتبر زیاد است؟

من به چگونگی ایجاد این جلسات نامعتبر پی بردم و متوجه شدم که به طور پیش فرض، اکسپرس جلسه برای هر درخواستی که کوکی پیوستی ندارد یک جلسه ایجاد می کند (شما می توانید به اینجا مراجعه کنید). در طول حمله DDoS، این منجر به ایجاد یک جلسه جدید برای هر درخواست شد که سپس در Redis ذخیره شد.

برای حل این مشکل، ما را تنظیم کردیم saveUninitialized: false گزینه:

const session = require('express-session');

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: false,
  cookie: { secure: true }
}));
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

رفع مشکل

پس از اجرای تغییر کد، یک اسکریپت برای حذف جلسات نامعتبر از Redis نوشتم. در حالی که امیدوار بودیم این مشکل حل شود، ذخیره سازی Redis با سرعت هشدار دهنده ای به رشد خود ادامه داد.

تحقیقات ادامه دارد

با وجود رفع اولیه، متوجه شدیم که پایگاه داده Redis همچنان به سرعت در حال گسترش است. هنوز چیزی اشتباه بود.

من عمیق تر در پایگاه کد حفاری کردم و آن را کشف کردم فلش بسته ای که برای انتقال پیام بین سرورها استفاده می کردیم. پس از بررسی بیشتر، متوجه شدم که هنگام دسترسی به پیام ها:

const { msg } = req.flash();
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بسته یک شی خالی را به آن اختصاص می دهد req.session.flash اگر یکی از قبل وجود نداشته باشد:

var msgs = this.session.flash = this.session.flash || {};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این اصلاح از req.session باعث شد اکسپرس جلسه برای ذخیره جلسه در Redis. عملکرد فلش در نقاط پایانی عمومی استفاده می شد، که باعث می شد جلسات کاربر خالی بماند و منجر به درج جلسات جدید با هر درخواست می شد.

مسیر رسیدن به وضوح

برای حل این مشکل، کد را تغییر دادم تا پس از خواندن پیام، جلسه را از بین ببرد، همانطور که در زیر نشان داده شده است:

const { msg } = req.flash();

req.session.destroy();
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و بدین ترتیب، سفر کارآگاهی به پایان رسید.

در نهایت، اگر مقاله مفید بود، لطفا کف بزنید 👏و فالو کنید، ممنون!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا