آموزش بلاک کردن آیپی یک منطقه با GeoIP در سی پنل
بلاک کردن ترافیک یک کشور روی سرور cPanel از دو نقطه شدنی است: در سطح فایروال (مثلاً گزینهی CC_DENY در CSF یا یک set در nftables) که بسته را پیش از رسیدن به آپاچی دور میاندازد، و در سطح وبسرور با ماژول GeoIP و چند خط در .htaccess که سادهتر ولی کندتر و کماثرتر است. اما پیش از هر دو، این را بپذیرید: مسدودسازی کشوری مشتری واقعی شما را هم میبندد و کاربری که VPN روشن کند، بهسادگی از آن رد میشود.
پیش از اینکه یک کشور را ببندید
این تصمیم معمولاً در اوج عصبانیت از لاگهای شلوغ گرفته میشود و هزینهاش بعداً پرداخت میشود. چهار واقعیتی که باید قبلش بدانید:
- مشتری واقعی هم بلاک میشود. کاربری که موقتاً خارج از کشور است، همکاری که در سفر به پنل وصل میشود، خزندههای موتورهای جستجو، وبهوک درگاهها و سرویسهای مانیتورینگ بیرونی، همگی از آیپی کشورهای دیگر میآیند.
- دور زدنش بیزحمت است. کسی که قصد سوءاستفاده دارد، اولین کارش عوض کردن آیپی خروجی است. کسی که واقعاً پشت در میماند، بازدیدکنندهی معمولی است.
- جلوی حملهی توزیعشده را نمیگیرد. باتنت ذاتاً چندکشوری است؛ بستن چند کشور فقط بخشی از منابع حمله را حذف میکند.
- دیتابیس ژئو هم خطا دارد، هم کهنه میشود. تخصیص رنجهای آیپی مدام جابهجا میشود؛ دیتابیس بهروز نشده بعد از مدتی هم آدم بیگناه را میبندد و هم هدف اصلی را رد میکند.
یک تفکیک هم لازم است: اگر هدف شما اصلاً بلاک نیست و میخواهید کاربر هر منطقه به نزدیکترین سرور هدایت شود، ابزارش مسیریابی جغرافیایی در لایهی DNS است نه فایروال؛ آنجا کسی بسته نمیشود، فقط به مقصد نزدیکتر راهنمایی میشود.
راهکارهایی که معمولاً بهتر جواب میدهند
در بیشتر موارد، مشکل واقعی «رفتار» است نه «جغرافیا». این گزینهها را اول امتحان کنید:
- محدودسازی نرخ اتصال. در CSF پارامترهای
CT_LIMIT،CONNLIMITوPORTFLOODبرای همین ساخته شدهاند و در Nginx دستورlimit_req. این کار آیپی پرفشار را میبندد، فارغ از اینکه کجاست. - fail2ban و cPHulk. برای تلاشهای ورود ناموفق، بخش cPHulk Brute Force Protection در WHM همین کار را میکند و fail2ban هم از روی لاگ آپاچی الگوی حمله را میشناسد و آیپی را موقت میبندد.
- WAF. ModSecurity که در WHM با یک مجموعه قوانین (vendor) فعال میشود، درخواست را بر اساس محتوایش رد میکند؛ یعنی تزریق SQL را میبندد، نه کشور فرستنده را.
- بلاک بر اساس امضای رفتاری. نرخ بالای خطای
404،User-Agentجعلی یا اسکن پشتسرهم مسیرهایی مثل/wp-login.phpو/xmlrpc.phpسیگنالهای بهمراتب دقیقتری از پرچم کشور هستند.
روش اول: بلاک در سطح فایروال
اگر بعد از همهی اینها هنوز به بلاک کشوری نیاز دارید، فایروال درستترین جای آن است، چون بسته پیش از مصرف منابع آپاچی و PHP دور ریخته میشود. این لایه به دسترسی root نیاز دارد؛ روی هاست اشتراکی لینوکس با کنترلپنل cPanel نه به فایروال دسترسی دارید و نه به کانفیگ سطح سرور، و تنها کاری که از دستتان برمیآید قانون .htaccess در روش دوم است، آن هم فقط اگر میزبان، ماژول ژئو را از قبل فعال کرده باشد.
یک نکتهی مهم دربارهی خود CSF که باید بدانید: شرکت سازندهی آن (ConfigServer / Way to the Web) در سال ۲۰۲۵ تعطیل شد و توسعهی رسمی محصول متوقف شد. کد در آخرین نسخه با مجوز GPLv3 منتشر شد و cPanel یک فورک عمومی از آن را برداشته که دامنهاش فقط رفع اشکالات امنیتی و پایداری است، نه ساخت ویژگی جدید؛ روی سرورهای cPanel مسیر بهروزرسانی هم از مخزن قدیمی سازنده به مخزن خود cPanel منتقل شده است. یعنی CSF همچنان کار میکند و وصله میگیرد، ولی دیگر محصولی در حال توسعه نیست و بهتر است در طراحی بلندمدت امنیت سرور فقط روی آن حساب باز نکنید.
اگر CSF نصب است، در فایل /etc/csf/csf.conf این موارد را تنظیم کنید:
CC_DENYرا با کدهای دوحرفی کشور پر کنید، مثلاًCC_DENY = "CN,RU".CC_SRCمشخص میکند لیست رنجها از کدام دیتابیس ژئو گرفته شود. اگر MaxMind را انتخاب کنید، باید کلید لایسنس حساب خودتان را درMM_LICENSE_KEYبگذارید؛ دانلود بدون کلید کار نمیکند.LF_IPSET = "1"را روشن کنید. لیست رنج یک کشور هزاران شبکه دارد و بدونipset، جدول فایروال غیرقابلمدیریت و کند میشود.
سپس با csf -r فایروال را بازخوانی کنید و با csf -g 1.2.3.4 وضعیت یک آیپی نمونه را بگیرید.
بدون CSF هم میشود همین کار را دستی انجام داد: یک ست بسازید، رنجها را داخلش بریزید و یک قانون به آن وصل کنید:
ipset create cn_block hash:net · ipset add cn_block 1.2.3.0/24 · iptables -I INPUT -m set --match-set cn_block src -j DROP
روی توزیعهای امروزی iptables معمولاً فقط یک لایهی سازگاری روی nftables است؛ اگر از صفر شروع میکنید مستقیم با nft یک set از نوع ipv4_addr با فلگ interval بسازید. ست را هم باید با یک کرونجاب منظم از دیتابیس ژئو بازسازی کنید، وگرنه بهمرور بیاثر میشود.
هشدار: این دستورات ترافیک را بیصدا دور میریزند. اگر آیپی خودتان بهاشتباه داخل ست باشد، همان لحظه دسترسی SSH را از دست میدهید. قبل از اجرا مطمئن شوید راه دسترسی جایگزین (کنسول KVM یا IPMI) دارید و آیپی مدیریتیتان استثنا شده است.
روش دوم: ماژول GeoIP آپاچی و فایل .htaccess
مراحل نصب ماژول در همین وبلاگ توضیح داده شده است:
اینجا یک نکتهی مهم هست. آموزشهای قدیمی (از جمله نسخهی اول همین مطلب) از متغیر %{ENV:GEOIP_COUNTRY_CODE} استفاده میکنند. آن متغیر مال ماژول قدیمی mod_geoip و دیتابیسهای نسل اول با پسوند .dat است که MaxMind بازنشستهشان کرده و دیگر بهروزرسانی نمیشوند. اگر امروز همان را راه بیندازید، یا اصلاً دیتابیسی برای خواندن ندارد یا یک فایل چندساله را میخواند و نتیجهاش قابل اتکا نیست.
جایگزین امروزی ماژول mod_maxminddb است که دیتابیسهای قالب .mmdb (مثل GeoLite2-Country) را میخواند. اول بررسی کنید ماژول بار شده یا نه: httpd -M | grep -i maxminddb. اگر بستهاش در EasyApache 4 سرور شما موجود بود از همانجا نصبش کنید؛ در غیر این صورت باید دستی و در برابر همان آپاچی EasyApache 4 کامپایل شود. هر دو مسیر دسترسی root میخواهد، پس اگر روی سرور مجازی ایران با دسترسی کامل مدیریتی کار میکنید این گزینه در اختیارتان است.
ضمناً برای اینکه دیتابیس .mmdb کهنه نشود، باید ابزار geoipupdate را با شناسه و کلید لایسنس حساب MaxMind خودتان تنظیم کنید و اجرایش را در کرون بگذارید؛ بدون این کار فایل ژئو بهمرور از واقعیت عقب میافتد.
تعریف دیتابیس باید در سطح سرور یا ویهاست باشد، نه در .htaccess. در cPanel این خطوط را از مسیر WHM » Apache Configuration » Include Editor، بخش Pre Main Include بگذارید:
MaxMindDBEnable On
MaxMindDBFile COUNTRY_DB /usr/share/GeoIP/GeoLite2-Country.mmdb
MaxMindDBEnv MM_COUNTRY_CODE COUNTRY_DB/country/iso_code
بعد با httpd -t صحت کانفیگ را بگیرید و سرویس را با /scripts/restartsrv_httpd ریاستارت کنید. حالا در .htaccess سایت:
RewriteEngine On
RewriteCond %{ENV:MM_COUNTRY_CODE} ^(CN|RU)$
RewriteRule ^ - [F]
خروجی اینجا خطای 403 Forbidden است، نه ریدایرکت به سایت دیگری. نسخهی قدیمی این آموزش بازدیدکننده را به گوگل میفرستاد؛ این کار ترافیک ناخواسته را به دامنهی شخص ثالث پاس میدهد و برای کاربر هم گیجکننده است. یک صفحهی ایستا با پیام روشن یا همان 403 انتخاب درستتری است.
هزینهی پنهان روش .htaccess
این روش ساده است، ولی رایگان نیست. تا وقتی AllowOverride روشن باشد، آپاچی برای هر درخواست فایل .htaccess تمام پوشههای مسیر را دوباره میخواند و پارس میکند و یک جستوجوی ژئو هم بهازای هر درخواست انجام میشود. مهمتر آنکه وقتی این قانون اجرا میشود، اتصال TCP و دستدادن TLS از قبل کامل شده است؛ یعنی در برابر سیل درخواست، پهنای باند و CPU همچنان مصرف میشوند و شما فقط محتوای صفحه را دریغ کردهاید.
پس اگر به کانفیگ ویهاست دسترسی دارید، همین قوانین را بهجای .htaccess آنجا بگذارید و بلاک اصلی را به لایهی فایروال بسپارید؛ نصب و پیکربندی آن فایروال در راهنمای نصب فایروال CSF آمده است. ویرایش کانفیگ آپاچی روی سرور cPanel هم از همان مسیری انجام میشود که در آموزش کانفیگ آپاچی با EasyApache توضیح داده شده است.
تست کنید که واقعاً کار کرده است
بدون تست، فرض نکنید قانون فعال است. سه بررسی ساده:
- مقدار متغیر را موقتاً در یک صفحهی آزمایشی چاپ کنید تا مطمئن شوید
MM_COUNTRY_CODEواقعاً پر میشود. اگر خالی است، مشکل از ماژول یا مسیر دیتابیس است، نه از قانون Rewrite. - از یک آیپی داخل کشور هدف درخواست بزنید و کد وضعیت را ببینید:
curl -I https://example.comباید403برگرداند. - لاگ دسترسی دامنه را در
/etc/apache2/logs/domlogs/دنبال کنید. برای قوانین فایروال همipset listوcsf -gوضعیت واقعی را نشان میدهند.
و مهمتر از همه: بعد از اعمال قانون، آمار بازدید و فروش را دنبال کنید. افت غیرمنتظره یعنی بخشی از مشتریان واقعیتان را بستهاید.
جمعبندی
بلاک کشوری ابزاری درشت است: کمهزینه در اجرا، پرهزینه در عوارض جانبی. اگر مشکل شما اسپم فرم یا تلاش ورود است، rate limit و fail2ban و WAF جواب دقیقتری میدهند. اگر بعد از سبکسنگین کردن هنوز به آن نیاز دارید، در فایروال پیادهاش کنید، دیتابیس ژئو را زمانبندیشده بهروز نگه دارید، آیپی مدیریتی خودتان را استثنا کنید و نتیجه را اندازه بگیرید. اگر ترجیح میدهید این تنظیمات را تیم فنی روی سرورتان انجام و بازبینی کند، خدمات پشتیبانی فنی همین کار را پوشش میدهد.
