আক্রমণের মানচিত্রে একটি দেশের উপরে ঘন একটি দাগ, আর «পুরো দেশটাই নিষিদ্ধ করে দিই» নিয়মটি আপনা থেকেই মনে আসে। তাতে প্রায় কিছুই মিলবে না: বেরোনোর দেশ বদলাতে আক্রমণকারীর লাগে কয়েক মিনিট, অথচ নিষেধাজ্ঞার নিচে পড়বে আপনার নিজের দর্শনার্থীরা এবং ভ্রমণে থাকা আপনি নিজেই। আরও খারাপ, একটিমাত্র মেঘ থেকে আসা দৃশ্যমান ক্রলার অবরোধের পরে ঘরোয়া ঠিকানায় সরে যাবে এবং মানুষের থেকে আলাদা করা যাবে না।
নিচে পাঁচটি ধাপ রয়েছে যা একই সার্ভারে সত্যিই ফল দেয়: স্ক্যানার কেটে দেওয়া, গতি সীমিত করা, প্রয়োজনীয়টিকে না কাটা এবং তবুও দরকার হলে সঠিকভাবে অবরোধ করা। সবই একবারে যাচাই করে বসিয়ে নেওয়া যায়।
ধাপ 1. দেখুন দাগটি আসলে কে তৈরি করছে
প্রথমে অনুরোধের লগ খুঁজে নিন। একাধিক সাইটওয়ালা সার্ভারে access.log প্রায়ই ফাঁকা থাকে, আর নথিগুলি যায় সংশ্লিষ্ট ভার্চুয়াল হোস্টের লগে:
sudo ls -lS /var/log/apache2/*access*.log /var/log/apache2/*requests*.log 2>/dev/null
পরের সব কমান্ডে সেই ফাইলটি বসান যেটি ওই তালিকার শীর্ষে এসেছে। প্রথমে দিনের শীর্ষ ঠিকানাগুলি, তারপর তালিকার সবার উপরে থাকা ঠিকানাটি ঠিক কী চাইছে:
sudo awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20
sudo grep '^203\.0\.113\.' /var/log/apache2/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
দ্বিতীয় কমান্ডটি মূল প্রশ্নের উত্তর দেয়। ফলাফলে যদি আপনার নিজের সাইটের কয়েক ডজন আলাদা পাতা থাকে, তবে সেটি বিষয়বস্তু সংগ্রাহক: নিরীহ, আর তাকে দর্শনার্থী হিসেবে না গোনাই যথেষ্ট। যদি সেখানে /wp-login.php, /.env, /phpmyadmin এবং আরও এমন কিছু থাকে যা আপনার নেই-ই, তবে সেটি স্ক্যানার, আর তা নিয়ে কাজ করে ধাপ 2। nginx-এ লগ থাকে /var/log/nginx/-এ, ক্ষেত্রগুলি একই।
ধাপ 2. যা আপনার নেই তার অনুরোধের উপর jail
অনুরোধের পথ জাল করা যায় না — ঠিকানা আর User-Agent-এর বিপরীতে সেটিই হলো অভিপ্রায়। ফিল্টার /etc/fail2ban/filter.d/web-probes.local:
[Definition]
failregex = ^<HOST> .* "(GET|POST|HEAD) /(wp-login\.php|wp-admin|xmlrpc\.php|\.env|\.git/|phpmyadmin|administrator/)
ignoreregex =
Jail /etc/fail2ban/jail.d/web-probes.local:
[web-probes]
enabled = true
port = http,https
filter = web-probes
logpath = /var/log/apache2/*access.log
maxretry = 1
findtime = 1h
bantime = 1d
এখানে maxretry = 1 যুক্তিসঙ্গত: অন্যের প্রশাসন পাতায় কেউ হঠাৎ করে পৌঁছায় না। প্রয়োগ করুন এবং নিশ্চিত হোন যে ফিল্টারটি আপনার নিজের লগের লাইন ধরছে:
sudo fail2ban-regex /var/log/apache2/access.log /etc/fail2ban/filter.d/web-probes.local
sudo systemctl reload fail2ban && sudo fail2ban-client status web-probes
ধাপ 3. গতি সীমিত করুন
স্ক্যানার আর ক্রলার নিজেদের ধরা দেয় গতির মাধ্যমে, তারা কোন দেশ থেকে এসেছে তা নির্বিশেষে। একটি ঠিকানা থেকে মিনিটে ত্রিশটি পাতা এমন একটি সীমা যা তালিকা ঘেঁটে দেখা মানুষকে স্পর্শ করে না:
[http-flood]
enabled = true
port = http,https
filter = apache-overflows
logpath = /var/log/apache2/site_access.log
maxretry = 30
findtime = 60
bantime = 1h
নির্ণায়ক বিষয় হলো logpath-এ কোন লগ লেখা আছে। যদি সেই নকশার আওতায় নিয়ন্ত্রণ প্যানেল বা প্রশাসন অংশের লগও পড়ে যায়, তবে আপনি নিজেকেই আটকে ফেলবেন: সেখানকার একটিমাত্র পাতা শৈলী আর স্ক্রিপ্টের জন্য ডজনখানেক অনুরোধ টেনে আনে, আর ত্রিশটি জমে দুটি ক্লিকেই। তাই প্যানেলকে আলাদা একটি লগ ফাইল দেওয়া হয় যা jail-এর নকশার সঙ্গে মেলে না, আর স্থির ফাইলগুলিকে দীর্ঘ ক্যাশের মেয়াদ, যাতে ব্রাউজার প্রতিবার পাতা বদলের সময় সেগুলি আবার না চায়। তবুও ঘটে গেলে লক্ষণ: HTML আসে, সাজসজ্জা আসে না, পাতা ঝুলে থাকে। অবরোধ তোলা:
sudo fail2ban-client set http-flood unbanip 203.0.113.10
ধাপ 4. যা কাটা চলবে না তাকে রক্ষা করুন
অবরোধ চালু করার আগে ব্যতিক্রমগুলি লিখে রাখুন — না হলে সবার আগে সেগুলির নিচে পড়বে প্রয়োজনীয়টিই:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.0/24 66.249.64.0/19
এই লাইনে অবশ্যই কী থাকতে হবে এবং কেন:
- আপনার নিজের ঠিকানা বা দপ্তরের উপজাল। সার্ভারে প্রবেশাধিকার হারানোর সবচেয়ে সাধারণ কারণ আক্রমণ নয়, নিজের তৈরি নিয়ম;
66.249.64.0/19পরিসর। Google-এর অনুসন্ধান রোবট User-Agent দিয়ে চেনা যায়, কিন্তু তার যে অংশ JavaScript চালায় সেটি সাধারণChrome/Linuxহয়ে আসে এবং নিজের নাম বলে না। «তথ্যকেন্দ্র থেকে আসা ট্রাফিক আটকাও» ধরনের যেকোনো নিয়ম ঠিক তাকেই আঘাত করে, আর তারপর পাতাগুলি নিঃশব্দে সূচি থেকে বেরিয়ে যায়। সন্দেহজনক ঠিকানা উল্টো জিজ্ঞাসায় যাচাই করা যায়:dig -x 66.249.66.1 +shortgooglebot.comঅঞ্চলের একটি নাম ফেরত দেওয়ার কথা;- অর্থপ্রদানের বিজ্ঞপ্তির ঠিকানা। অর্থপ্রদান ব্যবস্থার webhook আসে AWS ও Azure সার্ভার থেকে। এই মেঘগুলি পুরোপুরি বন্ধ করে দিলে অর্থপ্রদানের নিশ্চয়তা আর পৌঁছাবে না, আর সে কথা জানবেন তখন, যখন গ্রাহক লিখবেন যে টাকা কেটে নেওয়া হয়েছে অথচ প্রবেশাধিকার নেই। পরিসরগুলি নেওয়া হয় আপনার অর্থপ্রদান সরবরাহকারীর নথি থেকে।
ধাপ 5. অবরোধ তবুও দরকার হলে — উপজাল আটকান, দেশ নয়
একটিমাত্র জাল থেকে আসা স্থায়ী ঘনত্ব, যা দিনের পর দিন টিকে থাকে এবং একই ধরনের অনুরোধের সঙ্গে আসে, সেটি তালিকা ধরে এগোনো একজনই নির্বাহক। এমন ক্ষেত্রে অবরোধ হয় লক্ষ্যভেদী ও মেয়াদি:
sudo ufw deny from 198.51.100.0/22 to any
sudo ufw status numbered
দ্বিতীয় কমান্ড দিয়ে নিয়মের ক্রমিক সংখ্যাটি মনে রাখুন: অবরোধ পরে ওই সংখ্যার মাধ্যমেই তুলতে হবে, sudo ufw delete <ক্রমিক সংখ্যা>। নিজের সঙ্গে একটি মেয়াদ ঠিক করুন — ধরা যাক এক মাস — আর তুলে নেওয়ার কথা পঞ্জিকায় লিখে রাখুন। «চিরকালের জন্য» বসানো নিয়মগুলি এক বছর পরে এমন তালিকায় পরিণত হয় যা ছুঁতে কেউ সাহস পায় না, কারণ ওই ঠিকানাগুলি কী কারণে সেখানে গেল তা কারও মনে থাকে না।
কোন উপজাল আটকাতে হবে তা প্রথম ধাপের ঠিকানা থেকে জানা যায়: whois 198.51.100.17 | grep -iE 'route|cidr|netname'।
এই পাঁচটি ধাপের পরে কী বদলায়
স্ক্যানার কাটা পড়ে উৎস অনুসারে নয়, অভিপ্রায় অনুসারে, আর ধরা পড়ে প্রথম অনুরোধেই। ক্রলাররা গতির সীমায় ধাক্কা খায়। অনুসন্ধান রোবট আর অর্থপ্রদানের বিজ্ঞপ্তি আগের মতোই যাতায়াত করে। যে একটিমাত্র চওড়া অবরোধ রয়ে গেছে, সেটিও লক্ষ্যভেদী, জানা মেয়াদ আর বোধগম্য কারণসহ।
মানচিত্র এতে কোথাও হারিয়ে যায় না, কিন্তু তার ভূমিকা বদলায়: দেশ বন্ধ করার জন্য নয়, বরং ঘনত্বটিকে আদৌ লক্ষ করার জন্য এবং এক সপ্তাহ আগের সঙ্গে মিলিয়ে দেখার জন্য তা দরকার। এর জন্য চাই ইতিহাস, চলতি দিনের ছবি নয়। এমন একটি মানচিত্র অবরোধের লগ আর খোলা পোর্টের তালিকার পাশে কেমন দেখায়, তা নিচের প্রদর্শনী পাতাগুলি দেখায়।