کد منبع: github.com/Alex0176/odoo-web-rbl — AGPL-3، با امکان استفادهٔ آزاد.
هرکس سرور Odoo را روی اینترنت راهاندازی کند، بازدیدکننده خواهد داشت؛ نه گاهبهگاه، بلکه بیوقفه. طی هفده روز، در پنج وبسایت خود ۷۳۱٬۲۹۷ درخواست را ثبت و تحلیل کردیم. ۱۱۰٬۵۱۱ مورد از آنها از طرف بازدیدکنندگان واقعی نبودند، بلکه جستوجوهای خودکار برای یافتن آسیبپذیریها، اطلاعات ورود و فایلهای پیکربندی بودند.
این مطلب به معرفی Web RBL میپردازد؛ ماژولی متنباز برای Odoo 19 Community که این ترافیک را شناسایی، ارزیابی، ثبت و مسدود میکند و فهرست مسدودسازی را بهصورت فهرست RBL منتشر میکند؛ یعنی در قالبی که فایروالها و پراکسیهای معکوس مستقیماً میخوانند. همهٔ آمارها از محیط عملیاتی واقعی به دست آمدهاند.
این ماژول چه کارهایی انجام میدهد — مروری بر قابلیتها
| قابلیت | عملکرد | تنظیم پیشفرض |
|---|---|---|
| تشخیص الگو | شناسایی تلاشهای شناسایی آسیبپذیری بر اساس مسیر و پسوند: .env، .git، فایلهای پیکربندی، کلیدهای سرویسهای ابری، دستورالعملهای ساخت CI/CD، WordPress، PHP، پیمایش مسیر، ابزارهای مدیریت پایگاه داده، GraphQL، اجرای فرمان از طریق /api/fs/exec و رابطهای مشابه | مسدودسازی |
| سه سطح برای هر الگو | مسدودسازی، شمارش یا گزارش — قابل تغییر برای هر الگو، بدون کدنویسی | برای هر الگو |
| آستانهها | تعداد دفعات تطبیق با یک الگو پیش از مسدودسازی؛ برای ورود، ده بار | ۱۰ بار برای ورود |
| محافظت از ورود | ورودهای ناموفق از طریق فرم و XML-RPC/JSON-RPC، بررسیهای ناموفق نشست و دسترسی به ابزار مدیریت پایگاه داده — ثبت در پایگاه داده، نه در حافظه | فعال |
| تشخیص ربات هنگام ورود | هرکس پس از ده تلاش ناموفق، پیام انتظار را نادیده بگیرد و به تلاش ادامه دهد، بلافاصله مسدود میشود | مسدودسازی |
| تشخیص رفتار | آدرسهایی که در پنج دقیقه بیست صفحهٔ خطا و تقریباً هیچ صفحهٔ موفقی دریافت میکنند؛ یعنی بهجای خواندن، نشانیها را حدس میزنند | گزارش |
| امتیازدهی از ۰ تا ۱۰۰ | چقدر احتمال دارد پشت این آدرس یک مهاجم باشد؟ بر اساس شدت الگو، تعداد الگوهای مختلف، تعداد روزهای فعالیت مشکوک، دامنههای هدف و تعداد موارد شناساییشده — همراه با توضیحی روشن و خوانا | فعال |
| مسدودسازی ورود بر اساس امتیاز | از یک امتیاز قابل تنظیم به بالا، ورود ممنوع میشود، اما مشاهدهٔ وبسایت همچنان امکانپذیر است | از ۴۰ به بالا |
| احتمال سرقت اطلاعات ورود | ورود موفق از یک آدرس مشکوک گزارش میشود و در صورت تمایل، بهصورت وظیفه ارجاع داده میشود — روزی یک بار برای هر آدرس | فعال |
| فهرستهای تهدید | گرههای خروجی Tor، Spamhaus DROP، FireHOL Level 1 و blocklist.de از پیش پیکربندی شدهاند؛ هر فهرست RBL دیگری را میتوان با وارد کردن آدرس آن اضافه کرد، با تطبیق روزانه و سطح جداگانه برای هر فهرست | گزارش |
| عدم دسترسی به بخش ورود | سطح چهارم برای فهرستها و کشورها: وبسایت قابل خواندن میماند، اما فرم ورود و رابطها بسته میشوند — پاسخی مناسب برای Tor | گزینه |
| کشور مبدأ | نمایش کشور برای هر مورد شناساییشده و هر آدرس با GeoLite2؛ ماژول با یک کلید مجوز رایگان، پایگاه داده را خودکار بهروز نگه میدارد | نمایش |
| قوانین کشورها | مسدودسازی، منع دسترسی به ورود، گزارش یا اجازهٔ صریح — برای هر کشور، عمداً بدون تنظیم پیشفرض | هیچکدام |
| پیکربندیهای نادرست | QNAP، Synology، Exchange-Autodiscover، ActiveSync و WebDAV/CalDAV/CardDAV شناسایی میشوند، هرگز مسدود نمیشوند و همراه با شرح مشکل و دامنهٔ مربوط در فهرست پیگیری قرار میگیرند | گزارش |
| یک تیکت برای هر آدرس | در صورت تمایل، برای هر مشکل شناساییشده تیکت ایجاد میشود — دقیقاً یک تیکت برای هر آدرس؛ تیکت بستهشده دوباره باز میشود و تیکت تکراری ساخته نمیشود | غیرفعال |
| صفحات الزامی و گردآورندههای داده | مسیر اصلی صفحهٔ مشخصات قانونی همیشه در دسترس میماند؛ امتحانکردن خودکار شکلهای دیگر این مسیر شناسایی میشود و در صورت تمایل مسدود خواهد شد | گزارش |
| فهرست مجاز | آدرسها و شبکههایی که هرگز مسدود نمیشوند؛ این فهرست روزانه از فایروال (نقاط مقابل VPN) و محدودههای آدرس منتشرشدهٔ Googlebot و Bingbot تکمیل میشود | فعال |
| انتساب به مشتری | هر مورد شناساییشده از شبکهٔ یک مشتری به همان مشتری نسبت داده میشود — بر اساس فهرست مجاز، هرگز با حدس دستی | فعال |
| دامنه و شناسهٔ هر مورد شناساییشده | درخواست برای کدام وبسایت و با کدام User-Agent ارسال شده است — هیچیک در گزارش دسترسی ثبت نمیشود | فعال |
| تحلیل | نمودار و جدول محوری برای همهٔ موارد شناساییشده: به تفکیک الگو، روز، دامنه، کشور و آدرس | فعال |
| طعمه | درخواستهای کاوشگر پاسخهایی ساختگی با یک مقدار نشانهگذار دریافت میکنند؛ هرکس بعداً آن مقدار را درخواست کند، پاسخها را خوانده است | غیرفعال |
| ارائهٔ RBL | فهرست مسدودسازی بهصورت فهرست سادهٔ آدرسها یا JSON، در نشانی اختصاصی محافظتشده با توکن — برای HAProxy، OPNsense و هر فایروالی که فهرستها را از URL میخواند | فعال |
هر آنچه با گزارش، خاموش یا گزینه تحویل داده میشود، آگاهانه چنین است: کسی که یک مسدودسازی را فعال میکند، باید این کار را به این دلیل کند که چند روز نظارهگر بوده و میداند چه کسی گرفتار میشود — نه به این دلیل که مقدار پیشفرض چنین خواسته است.
تحلیل: موارد شناساییشده به تفکیک الگو در هفت روز. بلندترین ستون مربوط به جستوجوی فایلهای .env است.
فهرستهای RBL: روشی استاندارد برای ارائهٔ فهرستهای مسدودسازی
RBL مخفف Real-time Blackhole List است. این اصطلاح از دنیای ایمیل آمده است؛ جایی که Spamhaus و دیگران از دههٔ نود میلادی فهرست آدرسهای فرستندگان مخرب را منتشر میکنند. سازوکار آن بسیار ساده است و دقیقاً به همین دلیل رواج زیادی دارد: یک آدرس در هر خط، قابل دریافت از طریق HTTP، با دریافت مجدد در فواصل منظم. نه قالبی که ابتدا به تجزیه نیاز داشته باشد، نه رابطی که برای استفاده از آن ابزار لازم باشد.
تقریباً هر فایروال و پراکسی معکوسی میتواند چنین فهرستی را بخواند و بر اساس آن قانون بسازد. سازندگان نامهای متفاوتی برای آن دارند، اما سازوکار همه یکسان است:
- OPNsense و pfSense — URL Table Alias: دریافت فهرست آدرسها از طریق HTTP، استفاده از آن بهعنوان نام مستعار در قوانین فایروال و بهروزرسانی ساعتی یا روزانه
- HAProxy — فایلهای ACL و Maps: استفاده از
src -f sperrliste.txtدر قانونhttp-request deny، با امکان بارگذاری مجدد از طریق API زمان اجرا، بدون راهاندازی مجدد - nginx — ماژول geo با فایل آدرسهای ضمیمهشده، یا دستورهای
denyاز یک فایلincludeتولیدشده - Fortinet FortiGate — External Block List یا Threat Feed: یک URL که فایروال فهرست IP را از آن دریافت میکند و در سیاستها به کار میبرد
- Palo Alto Networks — External Dynamic List (EDL): همان سازوکار، در قالب نوع مستقلی از اشیا در سیاستهای امنیتی
- Check Point — Custom Intelligence Feeds و IP Block Lists از طریق یک URL
- Cisco Secure Firewall (Firepower) — Security Intelligence Feeds با منابع فهرست اختصاصی
- Sophos Firewall — Third-Party Threat Feeds: فهرست آدرسها از یک URL بهعنوان منبع قوانین مسدودسازی
- Juniper SRX — Dynamic Address Entries از خوراکهای داده
- MikroTik RouterOS — Address Lists که با اسکریپت و
fetchاز یک URL تکمیل میشوند - CrowdSec — فهرستهای اختصاصی بهعنوان منبع Bouncerها در هر سیستم پشتیبانیشده
Web RBL فهرست مسدودسازی خود را دقیقاً در همین قالب ارائه میکند. فایروال بستهها را پیش از رسیدن به وبسرور حذف میکند — و همراه با آنها، هر تلاش دیگری از همان آدرس را نیز، مثلاً برای دسترسی به سرور ایمیل یا دروازهٔ VPN.
در هر دو جهت، اما در جای درست
این سازوکار در جهت عکس هم کار میکند: در Web RBL میتوان هر فهرست RBL دلخواهی را ثبت کرد — یک URL، یک سطح، تمام. گرههای خروجی Tor، Spamhaus DROP، FireHOL و blocklist.de از پیش پیکربندی شدهاند و فهرستهای دیگر با سه کلیک اضافه میشوند. ماژول هر فهرست را به محدودههای آدرس تبدیل میکند و هر درخواست را در چند میکروثانیه با آنها میسنجد.
با این حال: بهتر است فهرستهای بیرونی در فایروالی استفاده شوند که پیش از سرور قرار دارد. به سه دلیل. فایروال همهٔ سرویسها را میبیند، نه فقط HTTP — آدرسی که در فهرست Spamhaus است، باید در دسترسی به سرور ایمیل و VPN هم ناکام بماند. فایروال بستهها را پیش از برقراری اتصال حذف میکند و در نتیجه هیچ باری به سرور برنامه تحمیل نمیشود. همچنین نگهداری این فهرستها از قبل در همانجا انجام میشود؛ نسخهٔ دوم در برنامه، محل دومی است که ممکن است اطلاعاتش قدیمی بماند.
پس فهرستهای داخل ماژول چه کاربردی دارند؟ برای کارهایی که از عهدهٔ فایروال برنمیآید. فایروال فرم ورود را نمیشناسد. Web RBL میتواند برای آدرسی در فهرست Tor، دسترسی به ورود را مسدود کند و همچنان وبسایت را نمایش دهد — کسی که میخواهد ناشناس مطالعه کند، باید بتواند؛ کسی که میخواهد ناشناس گذرواژهها را یکییکی امتحان کند، نباید. همچنین میتواند ورود موفق از یک آدرس فهرستشده را بهعنوان مورد مشکوک گزارش کند. هر دو قابلیت به حضور فهرست در محل انجام ورود نیاز دارند.
امتیازدهی بهجای قضاوت حسی
آدرسی که یک بار /wp-login.php را درخواست کرده، با آدرسی که در دو روز با پنج الگوی متفاوت سه دامنه را هدف گرفته، یکسان نیست. Web RBL این رفتار را به امتیازی از ۰ تا ۱۰۰ تبدیل میکند — بر اساس مشاهدات خودش، بدون سرویس بیرونی و بدون ارسال پرسوجو به خارج.
یک رکورد: ۹۹ مورد شناساییشده، امتیاز ۸۴ و دلیل به زبان روشن — شدیدترین الگو، پنج الگوی جدی متفاوت، دو روز فعالیت مشکوک و بیش از بیست مورد شناساییشده.
امتیاز دو چیز را تعیین میکند. از یک حد قابل تنظیم به بالا، ورود ممنوع میشود — وبسایت همچنان قابل خواندن است، اما کسی که قبلاً دنبال اطلاعات ورود گشته، فرصت امتحانکردن اطلاعات پیداشده را نخواهد داشت. همچنین ورود موفق از آدرسی که امتیاز دارد گزارش میشود: در این حالت، کسی دیگر حدس نزده، بلکه اطلاعات را میدانسته است. یا کاربر مجاز از جای دیگری متصل شده، یا اطلاعات ورود به دست دیگری افتاده است — ماژول در این باره تصمیم نمیگیرد؛ موضوع را به کسی ارجاع میدهد که بتواند پیگیری کند. در این فرایند اصلاً به خود گذرواژه دست زده نمیشود.
فهرست مسدودسازی، فیلترشده بر اساس امتیاز ۴۰ و بالاتر: تعداد موارد شناساییشده، روزهای فعالیت مشکوک، دامنههای هدف و آخرین مسیر برای هر آدرس.
Web RBL از چه چیزهایی محافظت میکند — جزئیات قابلیتهای حفاظتی
۱. اطلاعات ورود کشف نمیشوند
بزرگترین دستهٔ حملات ثبتشده بهدنبال آسیبپذیریهای Odoo نیست، بلکه اطلاعات محرمانهٔ رهاشده را جستوجو میکند. در طول هفده روز:
- ۵۷٬۷۲۱ درخواست برای فایلهای
.env— محل نگهداری گذرواژههای پایگاه داده، کلیدهای API و مقادیر محرمانهٔ نشست - ۵٬۵۳۵ درخواست برای فایلهای پیکربندی
- ۴٬۳۸۸ درخواست برای اطلاعات دسترسی ابری:
credentials.json،service-account.json،firebase-adminsdk.json،rclone.conf،.git-credentials - ۲٬۸۱۱ درخواست برای پوشههای
.git— هرکس یکی از آنها را پیدا کند، تمام کد منبع را همراه با تاریخچهاش دانلود میکند - ۱٬۹۰۷ درخواست برای دستورالعملهای ساخت مانند
.github/workflows/deploy.ymlیا.gitlab-ci.ymlکه حاوی اطلاعات رجیستریها و نام کلیدها هستند
در این میان، عامل تعیینکننده تعداد درخواستها نیست، بلکه تعداد آدرسهای متفاوت است: /credentials.json از ۹۸ آدرس و /.git-credentials از ۹۲ آدرس درخواست شده است. این کار یک اسکنر تنها نیست؛ مجموعهای از روشهای رایج است که همزمان در سراسر جهان اجرا میشود.
۲. تلاشهای ورود بینتیجه میمانند — برای همیشه
Odoo سازوکار داخلی خود را برای کندکردن امتحانکردن پیاپی گذرواژهها دارد. این سازوکار سه محدودیت دارد که در خود کد منبع Odoo مستند شدهاند: شمارنده در حافظهٔ اصلی فرایند کاری نگهداری میشود و با هر راهاندازی مجدد صفر میشود؛ بهجای مسدودسازی، فقط تأخیر ایجاد میکند؛ و تنها تلاشهایی را میشمارد که به مرحلهٔ بررسی گذرواژه میرسند.
Web RBL در همان نقاط وارد عمل میشود، اما اطلاعات را در پایگاه داده ثبت میکند. در نتیجه:
- اطلاعات شمارنده پس از هر راهاندازی مجدد باقی میماند و میان همهٔ فرایندهای کاری مشترک است
- هر دو مسیر ثبت میشوند: فرم ورود
/web/loginو رابطهای/xmlrpc/2/commonو/jsonrpc - تلاشهایی که هرگز به مرحلهٔ بررسی گذرواژه نمیرسند نیز ثبت میشوند — مثلاً ورود بدون شناسهٔ معتبر نشست
- تلاش ناموفق برای دسترسی به مدیریت پایگاه داده نیز شمرده میشود؛ این جدیترین نوع تلاش برای ورود است
آستانهٔ تلاشهای ورود روی ده تنظیم شده و دلیل آن یک اندازهگیری است: از نُه ورود ناموفق در هفده روز، بیشترشان مربوط به مشتریانی بود که دسترسی خود را روی دستگاه دیگری تنظیم میکردند و دامنه را اشتباه وارد کرده بودند — در یک مورد، دامنهٔ خودشان را با خط تیره بهجای نقطه. بنابراین مسدودسازی در اولین تلاش ناموفق، بهجای مهاجمان، مشتریان را هنگام راهاندازی گرفتار میکرد.
اما کسی که با وجود پاسخ «لطفاً کمی صبر کنید» از سوی سرور همچنان در میزند، بیدرنگ مسدود میشود. این پیام را انسان میخواند و صبر میکند؛ کسی که نادیدهاش بگیرد، یک برنامه است. یک الگوی جداگانه با آستانهٔ صفر همین حالت را میگیرد و نمیتواند به همکاری آسیب بزند: به آنجا فقط کسی میرسد که پیشتر ده تلاش ناموفق پشت سر گذاشته و پس از آن ادامه میدهد.
۳. حمله دیگر باری به سرور تحمیل نمیکند
پیش از نصب ماژول، یک درخواست کاوشگر به مسیری مانند /@fs/../../.env پرهزینه بود: Odoo صفحهٔ خطا را پیدا و رندر میکرد، هنگام ساخت نشانی با بخشهای نقطهای مسیر به مشکل میخورد و سپس در نمایش صفحهٔ خطای همان صفحهٔ خطا هم شکست میخورد. دو گزارش پشته برای هر درخواست کاوشگر. در هفده روز، ۲۸٬۴۰۱ خطا از این نوع، بههمراه ۹٬۴۶۷ خطای ثانویه ثبت شد.
Web RBL در ir.http._match، یعنی پیش از مسیریابی، وارد عمل میشود. پاسخ بدون قالب، بدون دسترسی به پایگاه داده جز برای بررسی مسدودبودن، و بدون ثبت خطی در گزارش صادر میشود. بررسی فهرست مجاز، فهرستهای تهدید و قوانین کشورها از حافظهٔ نهان و روی محدودههای آدرس مرتبشده انجام میشود — تنها چند میکروثانیه، حتی با بیش از سی هزار محدوده.
۴. فایروال مهاجم را پیش از رسیدن متوقف میکند
فهرست مسدودسازی بهصورت فهرست RBL منتشر میشود که HAProxy و OPNsense مستقیماً آن را میخوانند. بدین ترتیب مهاجم اصلاً دیگر به وبسرور نمیرسد — و به هیچ سرویس دیگری روی همان میزبان هم نه. دسترسیِ یکبار شناختهشده بهعنوان مخرب، به این ترتیب با اثر بازگشتی از کل ماشین محافظت میکند.
سه سطح: مسدودسازی، شمارش، گزارش
هر درخواستی که به جایی نمیرسد حمله نیست. به همین دلیل Web RBL سه سطح را از هم تفکیک میکند و میتوان سطح هر الگو را بدون دستزدن به کد تغییر داد.
| سطح | درخواست محرک | پیامد برای آدرس |
|---|---|---|
| مسدودسازی | رد میشود | ۲۴ ساعت مسدود؛ پس از سه روز فعالیت مشکوک، مسدودسازی دائمی |
| شمارش | عبور میکند | فقط ثبت میشود، بدون مسدودسازی |
| گزارش | عبور میکند | همراه با شرح مورد شناساییشده ثبت میشود و هرگز مسدود نمیشود |
برای فهرستهای تهدید و کشورها، سطح چهارمی هم وجود دارد: منع دسترسی به ورود. وبسایت قابل خواندن میماند، اما فرم ورود و رابطها بسته میشوند. این راه میانهای است برای هر چیزی که مشکوک است، اما لزوماً مخرب نیست — Tor، یک محدودهٔ مرکز داده یا کشوری که در آن مشتری ندارید.
چه حملاتی شناسایی میشوند
همهٔ الگوها با ترافیک واقعی آزمایش شدهاند. تعداد آدرسهای متفاوت عمداً در کنار آنها آمده است — این عدد نشان میدهد که یک الگو فقط یک اسکنر را شناسایی میکند یا روشی رایج را.
| دستهٔ حمله | درخواستها | آدرسها |
|---|---|---|
استخراج اطلاعات .env | 57.721 | 223 |
| کاوشهای PHP | 12.237 | 256 |
| پیمایش مسیر با هدفی ارزشمند | 10.046 | 64 |
| فایلهای پیکربندی | 5.535 | 114 |
| کلیدهای دسترسی ابری | 4.388 | 152 |
| کاوشهای WordPress | 3.366 | 385 |
استخراج اطلاعات .git | 2.811 | 255 |
| شناسایی Odoo (مدیریت پایگاه داده، استعلام نسخه) | 2.500 | 213 |
زنجیرهابزارهای هوش مصنوعی و اجرای فرمان (/mcp، /api/fs/exec) | 2.450 | 74 |
| دستورالعملهای ساخت (CI/CD) | 1.907 | 88 |
| نقاط پایانی GraphQL | 1.878 | 71 |
جدیدترین دسته قابل توجه است. /api/fs/exec از ۵۴ آدرس متفاوت، ۳۶۹ بار درخواست شده است — این دسترسی برای خواندن نیست، بلکه تلاشی برای اجرای فرمان است. دو سال پیش چنین هدفهایی وجود نداشتند؛ آنها از رابطهای ابزارهای جدید هوش مصنوعی و صفهای وظایف آمدهاند. کسی که دفاع خود را فقط بر WordPress و PHP متمرکز کند، چیزی از این حملات نمیبیند. این دسته در امتیازدهی نیز به همین نسبت وزن بالایی دارد.
فهرستهای تهدید و کشور مبدأ
چهار فهرست، ۳۲٬۸۵۱ محدودهٔ آدرس، همگی روی «فقط گزارش». برای افزودن هر فهرست دیگر، تنها یک نشانی و یک سطح لازم است.
فهرست بیرونی ادعایی است که شخص دیگری، با دلایلی که نمیدانیم، دربارهٔ ترافیکی که هرگز ندیدهایم مطرح کرده است. ممکن است نادرست، قدیمی یا برای هدف دیگری تهیه شده باشد: blocklist.de عمدتاً آدرسهایی را گردآوری میکند که در جای دیگری تلاش کردهاند اطلاعات ورود SSH را حدس بزنند، و این دربارهٔ یک وبسرور چیز زیادی نمیگوید. به همین دلیل Web RBL فهرستهای بیرونی را جدا از فهرست مسدودسازی خودش نگه میدارد و تنظیم پیشفرض آنها گزارش است. فهرست مجاز خودمان هم همیشه اولویت دارد: مشتریای که میشناسیم، از ارزیابی شخص ثالث معتبرتر است.
کشور مبدأ در هر مورد و هر نشانی ثبت است. برای ارزیابی جایگزینناپذیر است — یک تلاش ورود از کشور خودمان ساعت ده صبح چیز دیگری است تا تلاش از کشوری که حتی یک مشتری هم ندارد. برای مسدودسازی همگانی چندان به کار نمیآید، و آمار خودمان این را میگوید: مهاجمان فهرست ما بیشتر از بازههای ابری در بلژیک، فنلاند و هلند میآمدند. مسدودسازی همهٔ آنچه بیرون از منطقهٔ آلمانیزبان است آنها را نمیگرفت — اما کارکنان خودمان را در تعطیلات و مشتریان را در سفر کاری میگرفت.
قوانین کشورها در ابتدا خالی هستند و دلیل آن در همین نما توضیح داده شده است.
گزارش پیکربندیهای نادرست بهجای مسدودسازی
رایجترین مورد در ترافیک واقعی نه حمله است و نه بازدیدکننده، بلکه نرمافزاری معیوب است که وبسرور را با سرویس دیگری اشتباه گرفته است:
- 1.367 فراخوانی رابط وب یک NAS از نوع QNAP — یک Sync-Client که مقصدش دیگر درست نیست. یک درگاه تنها 962 بار در زد.
- ۶۵ درخواست Autodiscover — یک Outlook که دامنهٔ وب را سرور Exchange خود میپندارد
چنین نشانیهایی هرگز مسدود نمیشوند. مسدودسازی عیب را برطرف نمیکند، پنهانش میکند — و کسی را میزند که دستگاهش از پیش نادرست تنظیم شده است. در عوض یک مورد با متن یافته و دامنههای درگیر ساخته میشود که در صورت تمایل خودکار به یک تیکت تبدیل میشود: برای هر نشانی دقیقاً یکی، و اگر بسته شود و نشانی دوباره جلب توجه کند، همان تیکت دوباره باز میشود، نه اینکه دومی ساخته شود.
QNAP، Synology، Exchange-Autodiscover، ActiveSync و همچنین برنامههای کلاینت WebDAV، CalDAV و CardDAV شناسایی میشوند. الگوها از نام دقیق فایلها و پوشهها استفاده میکنند، نه صرفاً پسوندها: در همان پوشهٔ /cgi-bin/، فراخوانیهای بیخطر همگامسازی درست در کنار کاوشهای متداولی مانند printenv.pl قرار دارند.
فهرست مجاز: آدرسهایی که هرگز مسدود نمیشوند
هزینهٔ اشتباه برای همهٔ آدرسها یکسان نیست. در مورد اسکنری از یک مرکز داده، تشخیص اشتباه هزینهای ندارد. اما در مورد نقطهٔ مقابل یک تونل ارتباطی بین شعب، هزینهاش قطع ارتباط کل شعبه است.
به همین دلیل فهرست دومی وجود دارد که پیش از فهرست اول بررسی میشود: آدرسها و شبکههایی که هرگز مسدود نمیشوند. این فهرست هیچ چیزی را از دید پنهان نمیکند — آدرسهای موجود در آن همچنان بررسی و ثبت میشوند و فقط پیامد مسدودسازی اعمال نمیشود. تفاوتش با استثنا در فایروال همین است: آن دید را از بین میبرد، این فقط تحمل را بیشتر میکند.
این فهرست هر روز از دو منبع پر میشود: از خودِ فایروال با همهٔ طرفهای مقابل VPN، تا یک تونل تازهراهاندازیشده وابسته به این نباشد که کسی به فهرست مسدودسازی فکر کند — و از بازههای نشانیِ منتشرشدهٔ Google و Microsoft برای خزندههایشان. فقط به این ترتیب میتوان یک Googlebot واقعی را از اسکنری که خودش را چنین مینامد تشخیص داد. موتورهای جستوجو هرگز نباید مسدود شوند؛ هر که آنها را بیرون بگذارد، وبسایتش را بدون راه بازگشت از نمایهسازی بیرون میبرد.
در این میان، قانونی وجود دارد که از تطبیق هم مهمتر است: پاسخ خالی هرگز باعث حذف نمیشود. اگر منبع پاسخ ندهد، پاسخ خالی بدهد یا پاسخش قابل فهم نباشد، فهرست بدون تغییر میماند. فهرست مجازی که هنگام اختلال خودبهخود خالی شود، در بدترین لحظهٔ ممکن همهٔ تونلها را هم از کار میاندازد.
اگر یک رکورد فهرست مجاز به مشتریای مرتبط باشد، هر مورد شناساییشده از شبکهٔ او به همان مشتری نسبت داده میشود. به این ترتیب، هر پیکربندی نادرست بلافاصله فرد مشخصی برای پیگیری دارد، بدون اینکه کسی مجبور باشد آدرسها را جستوجو کند.
اطلاعات الزامی و گردآورندههای خودکار داده
صفحهٔ مشخصات قانونی یک صفحهٔ معمولی نیست. این صفحه باید برای افراد در دسترس بماند، زیرا مسدودکردن آن دقیقاً همان تخلفی را ایجاد میکند که یک گردآورنده بهدنبالش است. در عین حال، نام و نشانی در همین صفحه قرار دارند — و به همین دلیل هدف گردآوری خودکار داده است.
در موج اخطارهای حقوقی در اتریش بابت استفاده از فونتهای Google، گزارشها نشان دادند که نامهها حاصل بازدیدهای موردی نبودند، بلکه از یک پویش خودکار گسترده ناشی میشدند: میزبانهای متفاوت و نامرتبط، با فاصلههای چند میلیثانیهای.
Web RBL این مسئله را با کاهش سطح برخورد بهجای ایجاد استثنا حل میکند. مسیر اصلی /impressum با هیچ الگویی مطابقت ندارد و همیشه در دسترس میماند. شکلهای دیگری مانند /impressum.php — که در یک سایت Odoo نمیتوانند وجود داشته باشند — گزارش میشوند و هرکس نخواهد گردآوری خودکار داده را بپذیرد، کافی است یک پارامتر را تغییر دهد. sitemap و robots از این قاعده مستثنا هستند و اصولاً قابل مسدودسازی نیستند: آنها حاوی اطلاعات شخصی نیستند و دریافتشان وظیفهٔ هر خزندهٔ موتور جستوجو است.
دامنه و شناسه: آنچه در گزارش دسترسی ثبت نمیشود
گزارش دسترسی werkzeug نه نام میزبان مقصد را ثبت میکند و نه شناسهٔ درخواستدهنده را. البته Odoo هر دو را دریافت میکند؛ بدون نام میزبان، در صورت وجود چند وبسایت اصلاً نمیتوانست سایت درست را انتخاب کند. اما بعداً نمیتوان این اطلاعات را در گزارش پیدا کرد.
Web RBL هر دو را برای هر مورد نگه میدارد. این به دو پرسش پاسخ میدهد که در غیر این صورت پاسخپذیر نیستند: کدام وبسایت مورد خطاب یک پیکربندی نادرست است — و در نتیجه دامنه به کدام مشتری تعلق دارد — و اینکه یک نشانی یک صفحه را میبیند یا همهٔ صفحهها را. چند دامنهٔ بیارتباط از همان نشانی نشانهٔ هجوم فراگیر است و امتیاز را بالا میبرد.
تحلیل یکی از وبسایتهای ما نشان داد که این شناسه چقدر اهمیت دارد: بیش از هفتاد درصد کل ترافیک آن سایت متعلق به یک درخواستدهنده بود که از بیش از صد آدرس استفاده میکرد. بدون شناسه، این ترافیک شبیه یک استخراجگر توزیعشدهٔ داده به نظر میرسید. اما این درخواستدهنده GPTBot، خزندهٔ OpenAI بود؛ مرتب فایل robots.txt را درخواست میکرد و رفتارش کاملاً مطابق قواعد بود.
جزئیات ملاحظات امنیتی
1. تشخیص پراکسی — خطرناکترین نقطه از همه
اگر Odoo پشت یک پروکسی معکوس اجرا شود و proxy_mode درست تنظیم نشده باشد، ماژول برای همهٔ درخواستها یک آدرس یکسان میبیند: آدرس پروکسی. در این حالت، مسدودسازی باعث میشود دسترسی همهٔ بازدیدکنندگان همزمان قطع شود.
به همین دلیل Web RBL پیش از هر مسدودسازی بررسی میکند که تشخیص آدرس قابل اعتماد باشد. وجود proxy_mode همراه با سرآیند ارسال درخواست الزامی است. اگر درخواستی از طریق پروکسی برسد اما proxy_mode فعال نباشد، یا بیش از یک پروکسی واسط وجود داشته باشد، ماژول از انجام عملیات خودداری میکند. در صورت تردید، مسدودسازی انجام نمیشود.
۲. شبکههای خودمان هرگز مسدود نمیشوند
محدودههای آدرس خصوصی، Loopback، Link-Local و CGNAT بهطور ثابت مستثنا شدهاند. این آدرسها تحت هیچ شرایطی، حتی بهصورت دستی، نمیتوانند وارد فهرست شوند. همین قاعده برای فهرستهای بیرونی هم برقرار است: محدودههای خصوصی و رزروشده و همچنین شبکههایی با گسترهٔ نامعقول، هنگام وارد کردن کنار گذاشته میشوند.
۳. خطای خود ماژول نباید وبسایت را از کار بیندازد
تمام فرایند بررسی در یک سازوکار محافظ اجرا میشود که همهٔ خطاها را مهار میکند. هر مشکلی در این بخش ثبت میشود و درخواست بدون تغییر به مسیر خود ادامه میدهد. ماژول حفاظتیای که با خطای خودش وبسایت را از کار بیندازد، از نبودن چنین ماژولی هم بدتر است. همچنین همهٔ پرسوجوها در مسیر پردازش درخواست، مستقل از زبان مرورگر بازدیدکننده و بدون مرتبسازی بر اساس فیلدهای ترجمهشده اجرا میشوند؛ انتخاب زبانی که نصب نشده است نباید باعث شکست بررسی شود.
۴. مشاهده پیش از مسدودسازی
پس از نصب، مسدودسازی آدرسهای فهرستشده برای درخواستهای عادی غیرفعال است. درخواستهای کاوشگرانه رد و ثبت میشوند و بقیه عبور میکنند. به این ترتیب میتوان چند روز گزارشها را زیر نظر گرفت و دید چه آدرسهایی واقعاً وارد فهرست میشوند، پیش از آنکه دسترسی کسی قطع شود. همین روال برای تشخیص رفتار، فهرستهای تهدید و قواعد کشورها هم برقرار است: ابتدا گزارش، سپس بررسی و مسدودسازی.
۵. الگوهای دقیق بهجای مسدودسازی گسترده
هزینهٔ تشخیص اشتباه یک بازدیدکننده بیشتر از نادیده ماندن یک درخواست کاوشگرانه است. به همین دلیل، هر الگو سطح مشخصی دارد که میتوان آن را جداگانه تغییر داد. پسوند فایل بهتنهایی بهندرت کافی است: برای .php، در برابر ۱۴٬۰۱۲ درخواست کاوشگرانهٔ واقعی، فقط تعداد اندکی پیوند قدیمی وجود دارد؛ برای .asp این نسبت برعکس است. چنین تصمیمهایی باید بر پایهٔ اندازهگیری باشند، نه حدس.
۶. مجازسازی دستی پابرجا میماند
هر که نشانیای را آزاد کرده، دلیلی داشته است. یک مورد دیگر این تصمیم را بیسروصدا باطل نمیکند.
۷. فهرست محافظت میشود، اما محرمانه نیست
نقطهٔ پایانی به توکن نیاز دارد و در نبود توکن معتبر، بهجای 403 پاسخ 404 میدهد؛ به این ترتیب حتی وجود این نشانی هم تأیید نمیشود. مقایسهٔ توکن در زمان ثابت انجام میشود. خود فهرست اطلاعات محرمانهای ندارد: فقط شامل آدرسهایی است که خودشان به سراغ ما آمدهاند.
۸. اطلاعات محرمانه جایی در سوابق ندارند
در ورودهای ناموفق، نام کاربری استفادهشده ثبت میشود، اما هرگز گذرواژه ثبت نمیشود. در بخش مدیریت پایگاه داده، هیچچیز از مقادیر ارسالی خوانده نمیشود؛ چون نخستین مقدار در آنجا گذرواژهٔ اصلی است و هر مورد ثبتشده در فهرست مسدودسازی، وارد تمام نسخههای پشتیبان پایگاه داده میشود. کلید مجوز GeoLite2 فقط در پارامتر سیستم نگهداری میشود و در هیچ خطی از گزارشها نمیآید.
۹. طعمه هیچ اطلاعات قابل استفادهای افشا نمیکند
Web RBL میتواند بهصورت اختیاری به درخواستهای کاوشگرانه، محتوای ساختگی حاوی یک نشانگر قناری منحصربهفرد برگرداند. هر کس بعداً این مقدار را درخواست کند، پاسخ جعلی را خوانده و بر اساس آن عمل کرده است؛ در این حالت هشدار کاذب منتفی است. طعمهها هیچ اطلاعات قابل استفاده، مسیر واقعی یا اطلاعات ورود معتبری ندارند. این قابلیت هنگام عرضه غیرفعال است، زیرا رفتار قابل مشاهدهٔ سیستم از بیرون را تغییر میدهد.
محدودیتهای ماژول
این ماژول جایگزین فایروال یا فایروال برنامهٔ وب نیست. الگوهای شناختهشدهٔ کاوش در مسیرها، ورودهای ناموفق و رفتارهای مشکوک را تشخیص میدهد؛ اما حمله به فرمها یا تلاش برای تزریق در پارامترها را شناسایی نمیکند.
همچنین فقط فعالیتهایی را میبیند که از طریق HTTP به آن برمیگردند. اینکه مهاجم با اطلاعات ورود سرقتشدهٔ پایگاه داده یا صندوق ایمیل چه میکند، از دید آن پنهان میماند؛ دقیقاً به همین دلیل نشانگرهای قناری، مسیر هستند و نه اطلاعات ورود.
این ماژول جای دقت و مراقبت را هم نمیگیرد: ماژولی که درخواستهای کاوشگرانهٔ .env را رد میکند، فایل .env را که سهواً در دسترس قرار گرفته، بیخطر نمیکند.
دسترسی به ماژول
Web RBL با مجوز AGPL-3 در دسترس عموم است و در محیط عملیاتی ما روی پنج وبسایت اجرا میشود:
github.com/Alex0176/odoo-web-rbl
این ماژول به Odoo 19 Community نیاز دارد و جز base و web وابستگی دیگری ندارد. اتصال به سامانهٔ تیکت اختیاری است و به سامانهٔ مشخصی وابسته نیست؛ اگر چنین سامانهای وجود نداشته باشد، صرفاً اقدامی انجام نمیشود. تعیین کشور مبدأ به پایگاه دادهٔ رایگان GeoLite2 از MaxMind نیاز دارد؛ اگر موجود نباشد، این فیلد خالی میماند و سایر بخشها مانند قبل کار میکنند.
مطالعهٔ بیشتر: جایگاه Web RBL در یک معماری امنیتی کامل، در کنار فایروال، احراز هویت دومرحلهای و مجوزهای دسترسی، همراه با راهنمای گامبهگام: ترکیب درست اجزای معماری امنیتی Odoo 19.
از پرسشها، دیدگاهها و گزارش خطاهای شما استقبال میکنیم؛ ترجیحاً در قالب Issue در GitHub.