پیشتر در نوشتهای با عنوان بررسی ترافیک بالای سرور گنجور توضیح دادم که پس از آن که گنجور به دلیل مصرف بالای پهنای باند مسدود شد، برای پیدا کردن علت مسئله گنجور را موقتاً به سرور دیگری منتقل کردم.
نتیجه روشن بود: با انتقال گنجور، ترافیک سرور اصلی بلافاصله افت کرد و با بازگرداندن گنجور، دوباره بالا رفت.
این آزمایش خیال مرا تا حد زیادی از بابت یک نگرانی مهم راحت کرد: به نظر میرسید این حجم ترافیک واقعاً مربوط به خود گنجور است و برنامه یا آلودگی دیگری روی سرور عامل آن نیست.
اما این فقط نیمی از مسئله را حل میکرد. حالا که میدانستیم ترافیک واقعاً از گنجور میآید، سؤال بعدی این بود که:
گنجور دقیقاً چه چیزی را با این حجم زیاد به اینترنت میفرستد؟
از آنجا که گنجور در این سالها بسیار بزرگ شده و سرویسهای مختلفی در کنار سایت اصلی آن کار میکنند، پاسخ این سؤال را نمیشد صرفاً از روی نمودار مصرف سرور پیدا کرد. بنابراین از ChatGPT خواستم لاگهای سرور را بررسی کند و به دنبال الگوی این مصرف بگردد.
این نوشته نیز حاصل همین بررسی است و به جانشینی از من توسط ChatGPT نوشته شده است. دادههای خام لاگ و اطلاعات مربوط به ساختار سرویسها را من در اختیار آن گذاشتم و تحلیل لاگها، دستهبندی درخواستها و نتیجهگیریهای این نوشته توسط آن انجام شده است.
برای اینکه نتیجه صرفاً بر اساس حدس نباشد، درخواستهای ثبتشده در لاگ IIS بر اساس نشانی IP، نوع برنامهٔ درخواستکننده، نشانی مورد درخواست و حجم دادهٔ ارسالشده بررسی شدند. در مورد API نیز درخواستهای داخلی خود گنجور از درخواستهایی که از اینترنت دریافت میشوند جدا شدند. سپس به جای شمردن صرف تعداد درخواستها، حجم واقعی دادهٔ ارسالی نیز بررسی شد تا معلوم شود کدام درخواستها واقعاً در مصرف پهنای باند نقش دارند.
نتیجه جالبتر از چیزی بود که انتظار داشتم.
گنجور فقط بازدیدکنندهٔ سایت ندارد
یکی از چیزهایی که ممکن است در نگاه اول فراموش کنیم این است که گنجور فقط یک وبسایت نیست.
سالهاست که API گنجور نیز در اختیار برنامهها و سرویسهای دیگر قرار دارد. برنامهای که بخواهد اطلاعات یک شاعر یا شعر را از گنجور دریافت کند، لازم نیست صفحهٔ وب گنجور را برای کاربر باز کند؛ میتواند مستقیماً از API اطلاعات مورد نیازش را بگیرد.
این ویژگی یکی از بخشهای مهم و مفید زیرساخت گنجور است. اما طبیعتاً هر بار که چنین درخواستی انجام میشود، سرور گنجور باید اطلاعاتی را به آن برنامه ارسال کند.
اگر این اتفاق چند هزار بار در روز بیفتد، مسئلهای نیست.
اما اگر یک محتوای مشخص صدها یا هزاران بار در روز درخواست شود، داستان فرق میکند.
دهها گیگابایت شعر
در بررسی لاگهای یک روز، API گنجور بیش از یک میلیون درخواست داشته و دهها گیگابایت اطلاعات به درخواستکنندگان خود ارسال کرده است.
بخش قابل توجهی از این درخواستها نیز مربوط به درخواستهایی بوده که برنامهٔ درخواستکننده خود را معرفی نکرده است؛ یعنی در لاگ سرور User-Agent آنها خالی است.
البته این نکته به خودی خود نشانهٔ خرابکاری نیست. برنامههای سادهای که برای ارتباط با یک API نوشته شدهاند ممکن است اصلاً User-Agent ارسال نکنند. بنابراین نمیتوان گفت هر درخواست بدون User-Agent یک درخواست مخرب است.
اما وقتی این درخواستها را دقیقتر بررسی کردیم، نکتهٔ بسیار جالبی دیده شد.
این حجم ترافیک عمدتاً صرف درخواست محتوای واقعی گنجور میشود.
یعنی کسی یا چیزی در حال درخواست کردن فایلها و نشانیهای تصادفی یا نشانیهای مربوط به آسیبپذیریهای معمول وب نیست؛ بخش بزرگی از ترافیک صرف دریافت شعر و اطلاعات شاعران گنجور میشود.
برای نمونه، یکی از درخواستهای پرتکرار مربوط به صفحهٔ حجیم فهرست غزلهای شمس مولانا بود که در یک روز بیش از ۱۸۰۰ بار درخواست شده و حدود یک و نیم گیگابایت ترافیک ایجاد کرده است.
صفحهای مربوط به آثار صائب بیش از یک گیگابایت ترافیک ایجاد کرده، و غزل اول حافظ، مثنوی مولانا، دیباچهٔ گلستان سعدی و تعداد زیادی از اشعار دیگر نیز در میان درخواستهای پرتکرار دیده میشوند.
و اینها فقط چند نمونهاند.
وقتی فهرست را ادامه میدهیم، تقریباً با فهرستی از ادبیات فارسی روبهرو میشویم: حافظ، سعدی، مولانا، فردوسی، صائب، عطار، شهریار، بیدل و شاعران بسیار دیگری که محتوایشان در گنجور نگهداری میشود.
این نتیجه برای من از یک جهت خوشحالکننده و از جهت دیگری نگرانکننده است.
خوشحالکننده از این جهت که آنچه سرور گنجور مشغول ارسال آن است، همان چیزی است که قرار بوده برای دیگران فراهم کند: متن شعر و اطلاعات مربوط به آن.
و نگرانکننده از این جهت که حجم درخواستها بسیار بیشتر از چیزی است که از بازدید معمول انسانها انتظار داریم.
چه کسی این همه شعر را میخواهد؟
این همان بخشی است که هنوز جواب قطعی برایش نداریم.
درخواستها از تعداد زیادی نشانی اینترنتی مختلف میآیند و بسیاری از آنها نام برنامهٔ مشخصی را اعلام نمیکنند. در بررسی اولیه نیز برای چند مورد از پرتکرارترین صفحات نتوانستیم یک نشانی IP مشخص پیدا کنیم که به تنهایی مسئول بخش عمدهٔ این مصرف باشد.
بنابراین فعلاً نمیتوان گفت یک نفر یا یک ربات مشخص در حال دانلود کردن گنجور است.
چند احتمال وجود دارد.
ممکن است برنامهها و سرویسهایی باشند که از API گنجور استفاده میکنند. ممکن است رباتها و خزندههایی باشند که محتوای گنجور را برای پردازش خودکار دریافت میکنند. ممکن است موتورهای جستوجو یا سرویسهای هوش مصنوعی و دادهکاوی بخشی از محتوا را دریافت کنند. و حتی ممکن است برنامهای با تعداد زیادی کاربر داشته باشیم که هر کاربر مقدار کمی از اطلاعات گنجور را دریافت میکند، ولی مجموع این درخواستها به عدد بزرگی میرسد.
در حال حاضر برای نسبت دادن این ترافیک به یکی از این گروهها شواهد کافی نداریم.
و ترجیح میدهم در این مرحله چیزی را که نمیدانیم به عنوان واقعیت مطرح نکنیم.
پس آیا سرور گنجور هک شده است؟
تا اینجا شواهدی که پیدا کردهایم چنین چیزی را نشان نمیدهد.
سرورهای متصل به اینترنت دائماً با درخواستهای خودکار مختلف مواجهاند؛ از درخواست برای فایل .env و .git گرفته تا تلاش برای پیدا کردن وردپرس و سایر نرمافزارهای آسیبپذیر. گنجور نیز از این قاعده مستثنا نیست.
اما این درخواستها بخش اصلی مصرف پهنای باند را تشکیل نمیدهند.
بخش عمدهٔ ترافیکی که باعث نگرانی ما شده، درخواستهایی برای خود محتوای گنجور است.
از طرف دیگر، همانطور که در نوشتهٔ قبلی توضیح دادم، انتقال موقت گنجور به یک سرور دیگر نیز نشان داد که با خارج شدن گنجور از سرور اصلی، ترافیک آن سرور به سرعت پایین میآید و با بازگشت گنجور دوباره بالا میرود.
در نتیجه، شواهد فعلی بیشتر به این سمت میرود که با یک مسئلهٔ مصرف بسیار زیاد و خودکار محتوای عمومی گنجور روبهرو هستیم، نه اینکه بدافزاری روی سرور نشسته باشد و از آن برای ارسال ترافیک استفاده کند.
البته این دو مسئله کاملاً مستقلاند و بررسی امنیت سرور همچنان کار درستی است؛ فقط فعلاً دلیلی نداریم که مصرف بالای پهنای باند را به یک آلودگی امنیتی نسبت دهیم.
مشکل اصلی چیست؟
مشکل در واقع این نیست که مردم یا برنامهها از گنجور استفاده میکنند.
اتفاقاً هدف گنجور همین است.
مشکل این است که استفادهٔ خودکار و تکراری از محتوا میتواند بسیار بیشتر از مصرف عادی کاربران انسانی باشد.
اگر یک شعر هزار بار درخواست شود، در نگاه اول هزار درخواست عدد بزرگی نیست. اما اگر پاسخ هر درخواست چند ده کیلوبایت باشد، همین یک شعر میتواند دهها یا صدها مگابایت ترافیک ایجاد کند.
حالا اگر صدها شعر به همین شکل درخواست شوند، به دهها گیگابایت میرسیم.
و اگر این اتفاق هر روز تکرار شود، در پایان ماه دیگر با یک مصرف کوچک روبهرو نیستیم.
این همان چیزی است که ظاهراً برای گنجور اتفاق افتاده است.
آیا میشود جلوی آن را گرفت؟
احتمالاً بدون اینکه API گنجور را ببندیم، میتوان مقدار قابل توجهی از این مصرف را کاهش داد.
یکی از اولین چیزهایی که باید بررسی شود استفادهٔ بهتر از cache است.
بسیاری از اطلاعات گنجور دائماً تغییر نمیکنند. شعر حافظ که امروز از API دریافت میشود، احتمالاً چند ساعت بعد همان شعر است. بنابراین اگر یک برنامه در فاصلهٔ کوتاهی همان اطلاعات را دوباره درخواست کند، منطقی نیست که سرور هر بار همهٔ اطلاعات را از ابتدا تولید و ارسال کند.
میتوان به برنامهٔ درخواستکننده اعلام کرد که پاسخ برای مدتی معتبر است و در این فاصله نیازی به دریافت دوبارهٔ آن نیست. در موارد مناسب نیز میتوان پاسخهای پرتکرار را در سمت سرور cache کرد.
راه دیگر، در صورت شناسایی مصرفکنندگان غیرعادی، اعمال محدودیت برای تعداد درخواستهاست.
البته این کار باید با احتیاط انجام شود. API گنجور یک سرویس عمومی است و نمیخواهیم به خاطر مقابله با چند مصرفکنندهٔ پرمصرف، برنامههایی که به شکل درست از گنجور استفاده میکنند نیز با مشکل روبهرو شوند.
هدف این نیست که درِ گنجور را ببندیم؛ هدف این است که هزینهٔ باز بودن این در را قابل تحمل کنیم.
هنوز یک سؤال مهم باقی مانده است
تا اینجا توانستهایم یک قدم مهم به جلو برداریم.
میدانیم که مصرف بالای پهنای باند واقعی است.
میدانیم که این مصرف با خود گنجور ارتباط دارد.
میدانیم که بخش قابل توجهی از آن از API گنجور میآید.
میدانیم که درخواستهای بسیار زیادی برای محتوای واقعی شعرها انجام میشود.
و میدانیم که بخش بزرگی از این درخواستها خود را با User-Agent مشخص معرفی نمیکنند.
اما هنوز نمیدانیم چه برنامهها و چه کسانی پشت این درخواستها هستند.
بررسی بعدی باید دقیقتر سراغ نشانیهای IP، زمان درخواستها و الگوی رفتاری مصرفکنندگان برود. شاید در این مرحله بتوانیم یک برنامه یا سرویس مشخص را شناسایی کنیم؛ شاید هم معلوم شود که این ترافیک حاصل جمع استفادهٔ تعداد زیادی مصرفکنندهٔ کوچک است.
در هر دو صورت، دانستن پاسخ این سؤال به ما کمک خواهد کرد که راهحل مناسبی پیدا کنیم.
فعلاً اما یک نتیجهٔ مهم به دست آمده است:
آن چند ده گیگابایت ترافیکی که هر روز از سرور گنجور خارج میشود، عمدتاً در حال تبدیل شدن به شعر و اطلاعات گنجور در سمت دیگر اینترنت است.
این شاید از یک نظر بهترین نوع مصرف پهنای باند برای یک سایت ادبی باشد؛ اما وقتی حجم آن به حدی میرسد که میتواند سرور را از دسترس خارج کند و هزینههای زیرساخت پروژه را چند برابر کند، دیگر نمیتوان از کنار آن گذشت.
بررسی این مسئله ادامه دارد.

سلام،
برای من گنجور فقط مجموعه شعر نیست، گرچه از خواندن شعرها بسیار لذت می برم. با این حال، بسیاری از داده ها و اطلاعات محیطی به ویژه حوادث بزرگی مانند سیلاب ها، خشکسالی ها، زمین لرزه ها و از این قبیل در آثار شاعران منعکس شده و برای من جستجو در آثار ادبی برای یافتن این حوادث جزو عادات پژوهشی است.
دست مریزاد برای این کار بزرگی که کرده اید.
کار بزرگ شما قابل ارزشگذاری نیست. به اندازه دهها وزارت فرهنگ و آموزش عالی کار کردهاید. سپاسگزار همیشگی شما هستم. بیگمان اینکه سرزمینمان در میان این حجم از هجوم نیروهای تاریکی تاب آورده و زنده مانده، به برکت وجود ستارههایی چون شماست. دیر زیید
کار بزرگ شما قابل ارزشگذاری نیست. به اندازه دهها وزارت فرهنگ و آموزش عالی کار کردهاید. سپاسگزار همیشگی شما هستم. بیگمان اینکه سرزمینمان در میان این حجم از هجوم نیروهای تاریکی تاب آورده و زنده مانده، به برکت وجود ستارههایی چون شماست. دیر زیید
خیلی از سرویسدهندگان کوچکتر از شما استفاده از توکن رو برای api ضروری کردهاند و تا مقدار زیادی از آن هم رایگان است. اما اگر مصرف یک توکن بیش از حد باشد میتوانید آنها را غیرفعال کنید و یا شارژ کنید. اما اگه این کار رو کردین لطفا سخاوتمندانه باشد! مثلا روزی ۱۰۰۰ درخواست و حداکثر ۲۰۰ مگابایت. شرکتهای بزرگتر اطلاعات رو bucket بندی میکنند و با هر درخواست api یک صفحه مثلا حداکثر ۵۰ بیت را میفرستند و برای صفحه دوم یک api request دیگر با شماره bucket بعدی (که در پاسخ قبلی ارسال شده است) لازم است.
When ingress and egress match, it’s a tunnel. What goes in, must come out