IBSng Structure
مقدمه
با توجه به گسترش روز افزون استفاده از شبکهها و راحتتر شدن دسترسی به شبکهٔ جهانی اینترنت، نیاز به نرمافزارهای مرتبط برای حفظ امنیت و بر قراری عدالت در مصرف نیز افزایش پیدا میکند. امنیت کاربران باید در مرحله اول با شناسایی (Authentication) و تعیین اجازهٔ دسترسی (Authorization) کنترل شود. همچنین مصرف کاربران باید مشخص و محدود باشد تا به یک کاربر اجازه داده نشود تا با استفادهٔ نابجا و بیرویه از منابع، امکان استفادهٔ مفید بقیه کاربران را نیز بگیرد. مدیران شبکه نیاز به ابزارهایی برای نظارت و کنترل شبکه خود دارند تا مشکلات و ضعفهای شبکهٔ خود را پیدا کنند و با کمک آنالیزهای آماری به رفع گلوگاه های شبکه بپردازند. در بسیاری از محیطها کاربران برای استفاده از سرویس خاص باید پول بپردازند که این اهمیت وجود برنامهای برای کنترل و محاسبه اعتبار کاربران را مشخص میکند. نرمافزارهای کنترل مشتری که در گذشته طراحی شدهاند فاقد امکان گسترش و پشتیبانی سرویسدهندههای جدید است و از امکان یکپارچه بودن سرویسهای مختلف نیز برخوردار نیستند. همچنین نرمافزار های موجود بر روی سکوهای بازمتن ناقص و ابتدایی بوده و به علت تقاضاهای فراوان برای توسعه تواناییهای نرمافزار، IBSng طراحی و پیاده سازی شد. نرمافزار IBSng با حمایت شرکت پارس پویش توسط اینجانب طراحی و پیادهسازی گردیده است.
اهداف پروژه
IBSng نرمافزاری برای مدیریت سرویسهای اینترنتی از قبیل سرویسهای Dial UP، شبکههای LAN، شبکههای Wireless و خدمات Voice Over IP می باشد. IBSng در این سرویسها وظیفهٔ مدیریت مشتریها را بر عهده دارد. ایجاد محدودیت برای مشتری از قبیل مدت تماس، میزان استفاده و شناسایی و امنیت مشتریان از وظایف نرمافزار می باشد. نرمافزار باید قابلیت کار همزمان با چند سرویس و چند سرویسدهنده (Ras) را داشته باشد. برای رابطه با سرویسدهندگان از پروتکل RADIUS (مطابق با استاندارد RFC 2865, 2866) استفاده شود. به دلیل استفاده نرمافزار در مراکز سرویسدهنده، نرمافزار باید قابلیت پشتیبانی از تعداد بالای 5000 کاربر همزمان را داشته باشد. همچنین روالهای ساده برای گرفتن و بازیابی نسخهٔ پشتیبان و پایدار بودن نیز از اهداف اولیهٔ نرمافزار است. امکان پشتیبانی از زبانهای مختلف برای پوسته و خطاهای نرمافزار با استفاده از استاندارد Unicode هم جزء اهداف طراحی نرمافزار میباشد.
ساختار نرمافزار
سیستم میزبان-مشتری
IBSng از سیستم میزبان مشتری برای سرویسدهی در شبکه استفاده میکند.این سیستم هم در رابطه پوسته نرمافزار با مشتری و هم رابطه هسته نرمافزار با پوسته به کار می رود.
پوسته/هستهٔ نرمافزار
نرمافزار از دو قسمت که بصورت منطقی از هم مستقل هستند تشکیل شده است. هستهٔ نرمافزار که با زبان Python نوشته شده و بصورت سرویس (daemon) همیشه بر روی سرور میزبان در حال اجراست. هسته که خود از زیرسیستمهای کوچکتری تشکیل شده تمام وظایف نرمافزار بجز نمایش خروجی را انجام میدهد. نمایش خروجی و ارتباط با کاربر وظیفهٔ قسمت پوسته است که با زبان PHP و Python نوشته شده است. مزیت روش پوسته/هسته در جدا شدن منطق برنامه از نمایش خروجی و امکان توسعه دادن چندین پوسته مثلا پوسته محلی (Native) بجای مبتنی بر وب و امکان cache کردن اطلاعات در هسته است. همچنین با این روش هسته به راحتی اطلاعات را در اختیار script ها و نرمافزارهای دیگری که نیاز به یکپارچه(integrate) شدن با IBSng را دارند قرار میدهد. نمونهٔ این نرمافزارها، نرمافزار حسابداری کاربران است که با این روش به IBSng متصل میشود. همچنین این سیستم با چند لایه کردن نرمافزار و چک کردن سطح دسترسی در هر لایه و محدود کردن ورودی برنامه به روش ورودی استاندارد هسته، امنیت بیشتری را فراهم میکند. به دلیل جدا بودن پوسته، پیچیدگی توسعهٔ پوستهٔ ساده و زیبا تا حد زیادی کنترل شده و تاثیر منفی بر قسمت حساس هسته ندارد. رابطه با پایگاه دادهها نیز مختص به هسته است و پوسته تمامی اطلاعات خود را از هسته میگیرد. رابطه بین پوسته و هسته از طریق یک اتصال TCP و محتوا با استفاده از پروتکل XML-RPC منتقل میشوند. پروتکل XML-RPC ساختار های زبان مثل آرایه ها و متغیر ها را با بیان کردن آنها بصورت XML منتقل میکند. همچنین قسمتی از پوسته که با زبان پایتون نوشته شده، علاوه بر XML-RPC از پروتکل SOAP هم برای ارتباط با هسته استفاده میکند. در هسته زیرسیستمی به نام سرور وجود دارد که وظیفهٔ آن مدیریت ورود اطلاعات به هسته است. این زیرسیستم اطلاعات را از طریق اتصال TCP دریافت میکند و آنها را به شکل ساختارهای محلی زبان در میآورد. سرور، API مشخصی را در اختیار بقیهٔ زیرسیستمها میگذارد که بتوانند توابع جدیدی را در سرور ثبتنام کنند تا به پوسته سرویسدهی کنند. به این توابع Handler گفته میشود. Handler ها باید سطح دسترسی کاربر درخواستدهنده و ورودی را از نظر کامل بودن اطلاعات (و نه صحت آنها) چک کند. پوسته فقط مجاز به استفاده از Handler های ثبتنامشده در سرور میباشد.
Authentication / Authorization
۴ نقش در IBSng وجود دارد. Admin, Internet User, VoIP User, Anonymous. هر درخواست که به سرور هسته انجام میشود باید شامل نقش، نامکاربری و رمز عبور باشد. Handler ها وظیفهٔ Authenticate کردن هر درخواست را بر عهده دارند. نقش Anonymous برای درخواستهایی به کار میرود که نیاز به سطح دسترسی خاصی ندارند و برای همه قابل دسترسی است. نقش Internet User و VoIP User برای درخواستهاییست که از طرف کاربران به هسته داده میشود. کاربران تنها دسترسی به اطلاعات کاربری خود دارند. نقش Admin یا مدیر که پراستفادهترین نقش است، برای مدیران سیستم به کار میرود. مدیران علاوه بر شناسایی شدن در Handler ، مجاز بودن آنها برای انجام درخواست مورد نظر نیز بررسی میشود. مجاز بودن بر اساس سیستم Permission ها تعیین میشود. هر Permission نشاندهنده نوع دسترسی به قسمتی از امکانات هسته است. Permission ها انعطافپذیری زیادی در تعریف مدیران سیستم پدید میآورند. لیست کامل Permisson ها و توضیحات آنها در قسمت راهنمای مدیران آمده است.
Subsystem Modules
همانگونه که گفته شد، هسته از زیرسیستمهای مختلفی تشکیل شده است. هر کدام از زیرسیستمها در یک شاخهٔ مخصوص زیرِ شاخهٔ اصلی هسته ساخته شده است. هر زیرسیستم از چند ماژول Python تشکیل شده است. برای استاندارد شدن رابطهٔ زیرسیستمها، معمولاً هر زیرسیستم یک ماژول اصلی دارد که با اضافه شده عبارت main_ به نام زیرسیستم ساخته میشود (مثلاً charge_main برای زیرسیستم charge). ماژول اصلی، دروازه استفادهٔ زیرسیستمهای دیگر است. بسیاری از زیرسیستمها ماژولهای استاندارد دیگری مثل Loader برای گرفتن و در حافظه قرار دادن اطلاعات از پایگاه دادهها و یا Actions برای مدیریت اعضای زیرسیستم دارند. به طور معمول تابع init در ماژول اصلی هر زیرسیستم در زمان شروع به کار هسته صدا میشود و زیرسیستم کارهای لازم برای آغاز کار خود را انجام میدهد. بعضی از زیرسیستمها تابع shutdown هم دارند که در زمان پایان به کار هسته صدا میشود.
Plugins
در قسمتهای مختلف نرمافزار از Plugin ها برای ساده شدن اضافه کردن امکانات جدید استفاده میشود. Plugin Loader وظیفهٔ پیدا کردن و راهاندازی Plugin ها را بر عهده دارد. هر Plugin بطور ساده یک ماژول Python است که یک تابع init دارد و در شاخهٔ خاصی قرار گرفته است. تابع init هنگام راهاندازی توسط Plugin Loader صدا میشود. Plugin ها به ماژولهای دیگر هسته دسترسی دارد و معمولاً در تابع init ، خود را در قسمت مربوط ثبتنام میکنند. هدف از استفاده ار Plugin ها ساده شدن اضافه کردن امکانات جدید و همچنین جدا شدن کدهای غیرمربوط به هم در ماژولهای مختلف است.
Core Error Reporting
گزارش خطا از هسته به پوسته از طریق پروتکل XML-RPC انجام میشود. سرور در آخرین سطح با گرفتن تمام Exception ها و تبدیل آنها به توضیح متنی، آنها را به پوسته گزارش میدهد. خطاها در هسته به صورت متمرکز در ماژول errors نگهداری میشود هر خطا شامل یک کلید، یک بخش و یک توضیح است. خطاها با جفت کلید و بخش، قابل رجوع هستند و در سایر قسمتها از این جفت برای گرفتن توضیح خطا استفاده میشود. کلید خطا به دلیل ساده و منحصر به فرد بودن برای چک کردن و رجوع کردن سادهتر است. در ضمن با این روش امکان ترجمه خطاها به زبان دیگر به راحتی فراهم میشود. قرار گرفتن یکجای خطاها از تعریف مکرر یک خطا نیز جلوگیری میکند.
Core Event Logging / Debugging
هسته از رویدادهای پیش آمده در ۵ فایل گزارشبرداری میکند. این فایلها کمک زیادی در عیبیابی و رفع مشکلات میکنند. هسته از تمام درخواستهای سرور، درخواست های RADIUS ، درخواست های پایگاه داده و Exception های به وجود آمده در هسته، گزارشبرداری میکند. همچنین رویدادهای خاص در هسته بصورت دستی در این فایلها نوشته میشود. برای جلوگیری از بزرگ شدن بیش از حد این فایلها مکانیسمی برای پاک شدن اطلاعات قدیمی در نظر گرفته شده است. همچنین هسته امکانی برای اجرای کد دلخواه بر روی سرویسِ در حال اجرا فراهم میکند. این امکان برای بررسی وضعیت و اشکالیابی سرویسِ در حال اجرا مناسب است. این کار با بارگذاری کد مورد نظر توسط سرور و اجرای آن توسط Handler خاص انجام میشود. برای جلوگیری از مشکلات امنیتی این امکان فقط از روی سیستم میزبان و توسط مدیر سیستم قابل دسترسی است. این امکان همچنین اجازهٔ گرفتن اطلاعاتِ آماری از قسمتهای مختلف توسط برنامههای خارجی را میدهد.
Database Subsystem
زیرسیستم پایگاه دادهها وظیفهٔ رابطه با پایگاه دادهها و انجام درخواستها را بر عهده دارد. سایر زیرسیستمها برای اتصال به پایگاه دادهها باید از این زیرسیستم استفاده کنند. این زیرسیستم با فراهم کردن یک API مشخص، نرمافزار را از نوع پایگاه دادهها مستقل میکند. این زیرسیستم Transaction ها را کنترل میکند و در صورت بروز خطا Transaction را Rollback میکند. همچنین برای افزایش بازدهی و کم کردن سرآمد (overhead) اتصال به پایگاه دادهها، از Connection Pool استفاده میکند و اتصالات قبلی را دوباره به کار میگیرد. کار دیگری که برای بهینه کردن و افزایش بازدهی انجام میشود، استفاده کردن از Prepared Query است که سرآمد Parse و Plan هر درخواست پایگاه دادهها را حذف میکند.
Thread Subsystem
هسته از ریسمان (Thread) ها برای کارهای مختلف به صورت همزمان استفاده میکند. همچنین سرور و زیرسیستم RADIUS نیز از مدل ریسمان برای سرویسدهی به مشتریها استفاده میکنند. برای افزایش بازدهی، ریسمانها در یک Pool نگهداری میشوند و از آنها دوباره استفاده میشود. Thread Pool وظیفه ساختن ریسمانهای جدید و کنترل تعداد کل ریسمانها را بر عهده دارد. در سطح بالاتر Thread Pool Wrapper وجود دارد که وظیفه آن کنترل تعداد ریسمانها در هر زیرسیستم است. زیرسیستمها برای تخصیص ریسمان به Thread Pool Wrapper مخصوص خود درخواست می دهند. Thread Pool Wrapper ریسمانها را با استفاده از Thread Pool اختصاص میدهد. Thread Pool Wrapper تضمین میکند که شلوغ شدن یکی از زیرسیستمها مثل سرور باعث از کار افتادن کل سیستم به دلیل تمام شدن تعداد ریسمانهای مجاز نشود. در صورت شلوغ شدن یکی از زیرسیستمها، درخواست های بیش از حدِ مجاز آنها در صف قرار میگیرند و بعد از آزاد شدن ریسمانهای قبلی، شروع به کار میکنند.
Event Subsystem
زیرسیستم Event وظیفه انجام کارها در زمان معینی را بر عهده دارد. وجود این زیرسیستم به دلیل Event Driven بودن زیرسیستم کاربران است. به این معنی که زیرسیستم کاربر برای هر کاربر روی خط محاسبه میکند که تا چه مدت دیگر نیاز به چک کردن کاربر برای تغییر وضعیت است. زیرسیستمهای دیگر هم از این زیرسیستم استفاده میکنند. مثلا زیرسیستم DataBase برای چک کردن ارتباطهای خود با پایگاه دادهها بصورت دورهای از این زیرسیستم استفاده میکند. زیرسیستم دو ماژول دیگر برای ساده کردن کارهای پراستفاده فراهم میکند. Daily Events که وظیفهٔ انجام کارهای روزانه را بر عهده دارد و Periodic Events که وظیفه انجام دادن کارهای دورهای را دارد. کار اصلی این زیرسیستم این است که یک Callable Method و زمان باقیمانده تا اجرای آن را میگیرد و سپس در زمان مورد نظر توسط یک ریسمان جدید، آن Callable Method را اجرا میکند. این زیرسیستم در بهینه کردن زیرسیستم کاربران نقش اساسی دارد و سرآمد (Overload) کاربران روی خط را تا حد زیادی کم میکند، چون تا وقتی زمان Event فرا نرسیده، کاربر برای سیستم سرآمدی ندارد.
User Subsystem
این زیرسیستم وظیفه کنترل کاربران رویخط و اَعمال مختلف بر روی کاربران را دارد. تعداد زیادی از امکانات این زیرسیستم توسط سیستم Plugin فراهم میشود. در IBSng هر کاربر مشخصاتی دارد که هر مشخصه یک جفتِ اسم و مقدار است. به این مشخصهها Attribute گفته میشود. هر Plugin میتواند یک یا چند Attribute را کنترل کند. Plugin ها میتوانند ورود، تغییر و حذف Attribute در پایگاه دادهها را کنترل کنند، یا مقداری که به پوسته داده میشود را برای خواناتر شدن تغییر دهند. همچنین برای جستجوی Attribute ها نیز هر Plugin خودش باید تصمیمگیری کند. Plugin ها علاوه بر کنترل Attribute ها نقش اِعمال آنها بر روی کاربران رویخط را نیز بر عهده دارند. مثلا مشخصهٔ تاریخ إنقصا توسط Plugin مربوطه چک میشود و در صورت منقضی بودن کاربر از رویخط آمدن کاربر جلوگیری میشود. این Plugin ها خود را در UserPluginManager ثبتنام میکنند و با اولویت ثبت شده در زمان ورود به سیستم یا فرا رسیدن Event کاربر اجرا میشوند. برای هر کاربر رویخط، یک شیء از کلاس User در حافظه قرار میگیرد. سطحپایینترین ساختمانی که کاربران با آن نشان داده میشوند Loaded User است که Attribute های کاربر را حمل میکند. نرمافزار امکان کنترل چند نمونه از یک کاربر را دارد اما برای سادگی فرض شده که در یک زمان تنها یکی از نمونههای کاربر در حال بررسی شدن است. این محدودیت توسط یک Monitor اعمال میشود. طراحی Monitor شبیه سیستم یک قفل برای هر کاربر است، با این تفاوت که برای بهینهسازی، واقعاً برای هر کاربر یک قفل وجود ندارد. این فرض لزوم استفاده از قفل برای لیستها و متغیرها را در اکثر موارد حذف میکند. دو نوع کاربر Internet و Voice نیز توسط عضو user_type در User شناسایی میشوند. برای افزایش بازدهی در این زیرسیستم یک User Pool طراحی شده که Loaded User ها را نگهداری میکند. در واقع این شیء تنها یک مرتبه بارگزاری میشود و دفعات بعد در صورت وجود در Pool از آن استفاده میشود. با توجه به اینکه تعداد کاربران ممکن است خیلی زیاد باشد، حداکثری برای اندازهٔ این Pool در نظر گرفته شده که در صورت رسیدن به این حد، اشیاء جدید جایگزین اشیاء قدیمی میشوند. رابطهٔ این زیرسیستم با زیرسیستم Ras از طریق یک سیستم Message Passing فراهم میشود. دو نوع پیغام RasMsg و UserMsg برای این کار تعریف شدهاند. زیرسیستم Ras Message Dispatcher وظیفه دریافت پیغام و محول کردن آن به قسمتهای مختلف را دارد. پیغامها اشیائی Dictionary-Like هستند و دلیل استفاده از آنها انعطافپذیر شدن رابطهٔ بین دو زیرسیستم است.
Charge Subsystem
زیرسیستم Charge وظیفه کم کردن اعتبار کاربر را بر عهده دارد. به قوانینی که نحوه کم کردن اعتبار را مشخص میکند، قوانین شارژ (Charge Rule) گفته میشود. قوانین شارژ توسط مدیر سیستم مشخص میشود. شارژ توسط یک User Plugin به قسمت کاربران ارتباط پیدا میکند. برای کاربران رویخط، شارژ باید زمان تقریبی پایان اعتبار را مشخص کند و به قسمت Event اطلاع دهد. برای کاربران از نوع Internet شارژ مشخص میکند که به ازای هر دقیقه استفاده از سرویس و هر کیلو بایت رد و بدل اطلاعات، چقدر از اعتبار کاربر باید کاسته شود. برای کاربران از نوع VoIP شارژ براساس یک لیست از مقصدها و مقصد تماس گرفته شده توسط کاربر مشخص کند به ازاء هر دقیقه مکالمه چقدر باید از اعتبار کاربر کاسته شود. اصل پیچیدگی شارژ به دلیل امکان وجود چند نمونه از یک کاربر است که در این صورت هر نمونه ممکن است شرایط متفاوتی داشته باشد.
RADIUS Server
همانگونه که گفته شده بود ارتباط نرمافزار با دستگاههای سرویسدهنده از طریق پروتکل RADIUS است. RADIUS Server ِ نرمافزار بر پایهٔ پروژهٔ بازمتن PyRad نوشته شده و رفعاشکالها و امکانات جدیدی که در IBSng به آن اضافه شده نیز به پروژه اصلی برگردانده شده و در سایت وب پروژه PyRad موجود است. RADIUS Server درخواست ورود و خروج کاربران را از سرویسدهنده میگیرد و سپس به کد متناظر سرویسدهنده در IBSng میدهد. چون درخواست هر سرویسدهنده ممکن است متفاوت از سرویسدهندههای دیگر باشد، و روش برخورد با هر سرویسدهنده هم متفاوت است، به همین دلیل برای هر سرویسدهنده باید یک سرویسدهنده IBSng توسعه داده شود. زیرسیستم RADIUS Server همچنین وظیفه چک کردن فرمتهای مختلف پسورد که توسط سرویسدهندهها استفاده میشود را بر عهده دارد. این وظیفه بخاطر دسترسی به اطلاعات خام درخواستها به این زیرسیستم داده شده است. RADIUS Server در شروع به کار نرمافزار از Thread Pool یک ریسمان میگیرد و بصورت دائمی در حال سرویسدهی است. برای هر درخواست جدید یک ریسمان جدید اختصاص میدهد تا از بلوکه شدن سایر درخواستها توسط درخواستی که زیاد طول میکشد جلوگیری شود.
Ras Subsystem
زیرسیستم سرویسدهنده همانطور که گفته شد بعد از RADIUS Server درخواست را از سرویسدهنده دریافت میکند و یک RasMsg آماده میکند و به قسمت کاربر میفرستد. به دلیل استاندارد نبودن تمام درخواستها و نیز کافی نبودن اطلاعات بعضی از درخواستها، هر سرویسدهنده روش خود را برای انجام کارها دارد. Ras های مختلف مانند Plugin ها راه اندازی میشوند و باید خود را در RasFactory ثبتنام کنند. Ras ها وظیفهٔ دریافت و Dispatch کردن درخواستهای RADIUS را دارند. همچنین باید بتوانند چک کنند که آیا کاربری برای روی سرویسدهنده هست یا نه، و یا بتوانند کاربر را از روی سرویسدهنده بیرون کنند. هر سرویسدهنده باید از کلاس Ras مشتق شود و اعمالی که میتواند از کلاس بالاتر Override کند. نوع سرویسدهندگانی که هماکنون IBSng از آنها پشتیبانی میکند در قسمت راهنمای مدیران آمده است.
Integrated Mail Server
IBSng یک سیستم مدیریت پست الکترونیکی نیز دارد. با این سیستم میتوان به یک کاربر صندوق پست الکترونیکی اختصاص داد و Quota کاربر را نیز مشخص کرد. این زیرسیستم نیز توسط یک User Plugin به قسمت کاربران مربوط میشود. این زیرسیستم همراه با پروژههای بازمتن Postfix برای Mail Transfer Agent و Courier IMAP برای سرویسهای Imap, Pop3 کار میکند. فایل تنظیمات نمونهای برای ساده شدن راهاندازی در قسمت Addons پروژه قرار گرفته است.
Bandwidth Manager
این زیرسیستم میتواند پهنای باند مصرفی کاربران را محدود کند. این زیرسیستم برای کار از قوانین شارژ تبعیت میکند و در واقع میزان پهنای باند هر کاربر در قانون شارژ کاربر گنجانده شده است. محدود کردن پهنای باند در واقع توسط هستهٔ سیستمعامل انجام میشود و نرمافزار بصورت Dynamic با استفاده از ابزار سطح کاربر موجود با هسته سیستم عامل کار میکند. این روش امکان ساخت پهنای باند درختی را بسیار سادهتر کرده است. همچنین با پیوند دادن دو قسمت مختف از هستهٔ سیستمعامل برای Classify کردن Packet ها و سپس Shape کردن آنها امکان کنترل بر روی سرویسهای مورد استفاده کاربر را نیز فراهم کرده است. این روش مستقل از سرویسدهنده است و نیازمندی خاصی ندارد.
کتابخانه های خارجی استفاده شده در نرمافزار
- IPy
- این کتابخانه برای چک کردن و تبدیل آدرس های IP به هم بکار رفته است. Wrapper ip_lib برای کار با این کتابخانه است.
- PySNMP
- این کتابخانه برای ارتباط با سرویسدهندهها توسط پروتکل Simple Network Management بکار رفته است. Wrapper snmp برای کار با این کتابخانه است.
- JPGraph
- برای کشیدن گراف در پوستهٔ وب بکار رفته است.
- PyCrypto
- قسمتهایی از این کتابخانه برای رمزنگاری کلمات عبور به کار رفته. فقط قسمت مورد نظر در پروژه قرار داده شده است.