ভূমিকা
প্রথমে আমাদের অ্যাপ্লিকেশন সম্পর্কে একটু বলি। আমাদের অ্যাপ্লিকেশনটি Laravel-এ তৈরি, তবে এখানে আমি যে সমাধানটি শেয়ার করবো, সেটি সকল ফ্রেমওয়ার্ক বা কাস্টম অ্যাপ্লিকেশনের জন্য কার্যকর হবে।
আমরা ওয়ার্ল্ড ওয়াইড সফটওয়্যার ও গেমের কী বিক্রি করি। আমরা প্রায়ই হ্যাকারদের অ্যাটাকের শিকার হই। মাঝে মাঝে আমরা মিলিয়ন মিলিয়ন রিকোয়েস্ট পাই। আমরা Cloudflare Business প্ল্যান ব্যবাহার করি। Cloudflare মেক্সিমাম অ্যাটাক ব্লক করে দেয়।
মাঝে মাঝে হ্যাকাররা Cloudflare বাইপাস করে আমাদের সার্ভারে অ্যাটাক করে। আমরা রিকোয়েস্টের প্যাটার্ন দেখে সিকিউরিটি আপডেট করে থাকি।
গত ১ মাস ধরে আমরা একটি সমস্যার সম্মুখীন হচ্ছি। হ্যাকার ১-৩ মিনিটের মধ্যে কয়েক মিলিয়ন রিকুয়েস্ট Cloudflare বাইপাস করে আমাদের সার্ভারে পাঠাচ্ছে। এর ফলে আমাদের Redis Cache সার্ভার স্লো হয়ে যাচ্ছে এবং টাইমআউট ইরোর ফেইস করতেছি।
আমরা AWS ElastiCache Redis (auto failover, auto scaling enabled) ব্যবহার করি। এই আক্রমণ বন্ধ করতে না পেরে, আমরা সাময়িকভাবে ElastiCache Serverless-এ মাইগ্রেট করি। তবুও হ্যাকার আমাদের সার্ভারকে স্লো করতে সক্ষম হয়।
দুঃখের বিষয় হলো, হ্যাকার শুধুমাত্র হোমপেজে রিকুয়েস্ট দিয়েই আমাদের সিস্টেম স্লো করে ফেলছিল। আমাদের সব কুয়েরি এর রেজাল্ট ক্যাশে রাখা থাকে। হোমপেজেও কয়েকটি কুয়েরি আছে। কুয়েরিগুলো আমরা ভালো ভাবে চেক করেছি। এটাক দেওয়ার কোন স্কোপ নেই। এ নিয়ে আমরা ভালো পেইনে পড়ে যাই।
সার্ভার স্লো হয়ে যাওয়ার কারন
হ্যাকার মিলিয়ন রিকুয়েস্ট পাঠানোর ফলে ক্যাশ সার্ভারে প্রচুর Packets IN এবং OUT হচ্ছিল। কানেকশন সংখ্যা অনেক বেড়ে যাচ্ছিল। খুব অল্প সময়ের মধ্যে এত রিকুয়েস্ট ট্রান্সফার ও কানেকশন বেড়ে যাওয়ার কারণে সার্ভার স্লো হয়ে যাচ্ছিল।
Auto Scaling কাজ করছিল না, কারণ CPU Utilization ৩০-৪০ শতাংশের বেশি ছিল না। ৫০ শতাংশের বেশি না হলে স্কেলিং কার্যকর হয় না। আমরা ভেবেছিলাম ElastiCache Serverless দ্রুত স্কেল করতে পারবে, কিন্তু সেটি স্কেল করতে সক্ষম হয়নি।
এটাক এনালাইসিস
যেহেতু আমাদের দ্রুত একটি সমাধান দরকার ছিল, আমি একটি প্যাটার্ন খুঁজে বের করার চেষ্টা করতে থাকি। আমি Cloudflare, অ্যাপ্লিকেশন, এবং Redis-এর লগ এনালাইসিস করতে শুরু করি। কয়েকদিনের আক্রমণের মধ্যে একটি প্যাটার্ন খুঁজে পাই। প্যাটার্নটি হলো Redis Connections!
স্বাভাবিক অবস্থায় আমাদের ১৫ থেকে সর্বোচ্চ ৪০টি অ্যাকটিভ কানেকশন থাকে। এর বেশি কখনো হয় না। কিন্তু অ্যাটাকের সময় এটি ১০০+ ছাড়িয়ে যায়। আমি এই কানেকশন সংখ্যা ধরে অ্যাটাকটি প্রাথমিকভাবে প্রতিরোধ করার জন্য একটি পরিকল্পনা করি।
কিন্তু AWS-এ কানেকশন সংখ্যা ধরে কোনো Auto Scale করার অপশন নেই। তাই আমি কাস্টম সমাধান তৈরি করার পরিকল্পনা করি।
লোকাল টেস্টিং এনভারনমেন্ট
আমি লোকালি অনেক অ্যাকটিভ কানেকশন তৈরি করার জন্য redis-benchmark ব্যবহার করি। আর Redis মনিটর করার জন্য একটি ভালো টুল খুঁজতে থাকি। পরবর্তীতে আমি একটি পারফেক্ট টুল খুঁজে পাই, যার নাম Tiny RDM। এটি দিয়ে লোকাল এবং লাইভ Redis সার্ভার উভয়ই মনিটর করা যায়।
আমি benchmark দিয়ে ৫০০টি কানেকশন তৈরি করে, Laravel-এ Redis Facade ব্যবহার করে অ্যাকটিভ কানেকশন সংখ্যা বের করি। RDM এবং Laravel-এর কানেকশন সংখ্যা তুলনা করে দেখি, সংখ্যা সঠিক রয়েছে।
আপনি আপনার অ্যাপ্লিকেশনে Redis প্যাকেজ ইউজ করে কানেকশন সংখ্যা বের করতে পারবেন।
এরপর প্ল্যান করি, যেহেতু কানেকশন সংখ্যা পাওয়া গেছে, এখন এই সংখ্যা ৫০-এর বেশি হলেই বুঝবো যে হ্যাকার আক্রমণ শুরু করেছে। এরপর কিভাবে লাইভ সার্ভারে কানেকশন চেক করলে বেটার হবে সেটি ভাবতে থাকি।
কন্টিনিউয়াস কানেকশন চেক
কন্টিনিউয়াস কানেকশন চেক করার জন্য Middleware এবং Cron Job-এর কথা মাথায় আসে। আমি প্রতি মিনিটে কানেকশন চেক করার পরিকল্পনা করি, যার জন্য Cron-ই বেশি কার্যকর।
আমি একটি সার্ভিস ক্রিয়েট করে কন্ডিশনগুলো লিখে ফেলি। যদি ৫০-এর বেশি কানেকশন হয়, তাহলে Cloudflare-এর API ব্যবহার করে “Under Attack Mode” চালু করবে এবং Discord-এ নোটিফিকেশন পাঠাবে। “Under Attack Mode” চালু করার পর ২৫ মিনিট পর্যন্ত সক্রিয় থাকবে। এরপর পুনরায় অ্যাকটিভ কানেকশন চেক করবে। যদি ৫০-এর কম হয়, তাহলে “Under Attack Mode” বন্ধ করে দেবে।
এরপর জব-টি লাইভ করে ফেলি।
লাইভ করার পর
সল্যুশনটি কাল বিকেলেই লাইভ করেছি। রাত ৯:২৮ মিনিটে হ্যাকার অ্যাটাক শুরু করে, আর আমি তখন বাইরে ছিলাম। ঠিক তখনই অটো অ্যাকশন নিয়েছে। কানেকশন চেক করে “Under Attack Mode” চালু করেছে।
হ্যাকাররা এই প্রথমবার এমন প্রতিরোধের সম্মুখীন হলো। গতকাল সারারাত অ্যাটাক চালিয়েছে। মাঝে মাঝে অ্যাটাক বন্ধ রেখে সাইট চেক করেছে। অ্যাটাক শুরু করলেই “Under Attack Mode” চালু হয়ে যায়, আর অ্যাটাক থামালেই এটি বন্ধ হয়ে যায়। হ্যাকাররা সকাল ৫:৪৩ পর্যন্ত চেষ্টা করেছে।
আলহামদুলিল্লাহ, সল্যুশনটি সফলভাবে কাজ করছে।
এরপরেও Redis সার্ভার Down বা Slow হলে?
আমি একটি Service Provider ক্রিয়েট করে জাস্ট ক্যাশ চেক করেছি। যদি ক্যাশ সার্ভার ডাউন বা স্লো হয় তাহলে ক্যাশ ড্রাইবার চেঞ্জ হয়ে Array বা ফাইল করে দিবে। এটা করেছি শুধু সাইট আপ রাখার জন্য। আমরা Instant Notification পাবো এবং দ্রুত একশন নিতে পারবো।
try {
Cache::get('connection-test');
} catch (\Exception $e) {
Config::set('cache.default', 'array');
// Store log and notify also
}
আমরা Redis Sentinel ব্যবহার করিনি, কারণ AWS ElastiCache-এর ডিফল্ট Auto Scaling, Auto-failover, এবং Load Balancer ব্যবহার করেছি। এরপর Sentinel ট্রাই করবো।
পরিশেষে
স্টোরিটি শেয়ার করার উদ্দেশ্য হলো:
১. যদি আপনারা এরকম কোনো প্রবলেম ইতোমধ্যে সম্মুখীন হয়ে থাকেন এবং আরও ভালোভাবে সমাধান করে থাকেন, তাহলে অনুগ্রহ করে শেয়ার করবেন।
২. আমাদের মতো এ ধরনের প্রবলেমে পড়লে, সাময়িকভাবে এই সমাধানটি ব্যবহার করতে পারবেন।
আমরা আরও ভালো সল্যুশনের জন্য কাজ করে যাব। Cloudflare টিমের সাথে অ্যাটাকের স্যাম্পল নিয়ে আলোচনা করবো।
কষ্ট করে পড়ার জন্য আপনাদের সবাইকে ধন্যবাদ।