Shared rss feeds:

Servare Mentem - blog

Мой предыдущий блог

пятница, 30 мая 2008 г.

CADBiS часть I : JRadius и с чем его едят

Итак, я обещал продолжить повествование о своём проекте на "соискание степени магистра" :)... Ээ ну, в общем, тупо дипломном проекте.
Итак, что такое JRadius и почему я пишу про него, ведь в предыдущем посте, я, кажется, писал про Proxy-сервер? Так вот, к нему я ещё вернусь. А сейчас, считаю очень важным написать именно про JRadius.
Начну издалека. Самой большой проблемой при написании программ под UNIX становится отладка, особенно если большую часть рабочего времени проводишь в среде Windows. Конечно, можно возразить, что для Linux надо писать проги, сидя под Linux. Но тут я не могу согласиться. Я давно хочу перейти на Linux полностью - и дома и на работе, но не могу этого сделать по одной простой причине: на работе мне приходится писать софт в Ms Visual Studio под .NET, а под Linux это делать не представляется сколько-нибудь возможным...
Теперь многие могут возразить, что раз уж я сижу под Windows, зачем мне разрабатывать софт под *nix? Могу сказать только, что я почти уверен, что по надёжности и производительности Windows-сервера не сравнятся с никсами. Утверждаю сейчас голословно, не хочу развязывать холивары. Если у кого-то возникли сомнения - Google вам в помощь и различные форумы типа "Windows Server vs Linux server". Для меня сейчас этот вопрос не стоит. Я знаю из личного опыта, что хорошо настроенный сервер FreeBSD надёжнее и производительнее хорошо настроенного сервера Windows Server 2003 и имеет гораздо больше удобных, полезных, а главное открытых и бесплатных серверных решений. Такой сервер способен работать буквально годами без сбоев и перезагрузок.
Я немного отвлёкся от темы. Вернёмся к защите моего бакалаврского проекта. Передо мной стояла задача аналогичная той, которая встаёт перед небольшими Интернет-провайдерами или же перед системными администраторами небольших компаний где необходим доступ в Интернет и возможность отслеживать и ограничивать использование этого доступа. А именно: нужно было поднять Интернет-шлюз с аутентификацией и организацией Интернет-доступа через VPN-канал. Каждый пользователь имеет собственный аккаунт с паролем. Каждому аккаунту сопоставлен тариф (группа), которая обеспечивает ему определённый уровень привилегий (например, разрешение/запрет на доступ в определённое время суток, ограничение максимального объёма Интернет-трафика и т.д.).
Решение, ставшее уже классическим в подобной ситуации - это: FreeBSD-сервер с установленным MPD (Multilink PPTP Daemon) и FreeRADIUS. Ну и различные прочие сервисы типа radacct, squid, freenibs, mabill etc. В общем-то и моё решение в рамках бакалаврского проекта заключалось в выборе связки FreeRADIUS+FreeNIBS. Единственное - мне пришлось немного модифицировать сам FreeNIBS, написать к нему свой интерфейс (веб-морду) и выбросить ненужную функциональность. Система отлично себя зарекомендовала и в течении 2-х лет успешно работала практически без сбоев. Попутно росла функциональность системы введением и совершенствованием прокси-сервера, который отслеживал посещаемые сайты, а заодно запрещал или разрешал к ним доступ. Но в определённый момент захотелось получить от системы большую гибкость, чем она обеспечивала. К тому же к тому времени уже был готов прототип прокси-сервера, реализованного на Java, который показал, что программирование на Java полностью избавляет от проблемы кроссплатформенности и сложности отладки приложения на другой платформе. Это даёт очень высокую степень гибкости и расширяемости системы. При этом можно писать, отлаживать и профилировать приложение сидя под любой ОС. Потом просто нужно будет скопировать собранную версию на выбранную платформу, и вуаля - она работает точно так же!
И вот тогда я занялся поисками возможности реализовать управление подключениями тоже на Java, чтобы полностью переписать функционал, который предоставляет FreeNIBS на свой лад.
После довольно продолжительных поисков решение было найдено. JRadius - это Java-framework с открытым исходным кодом, реализующий клиентский и серверный функционал протокола RADIUS. JRadius-клиент позволяет вам реализовать аутентификацию и аккаунтинг по протоколу RADIUS в собственном Java-приложении. Cервер JRadius - это движок обработки RADIUS-протокола, который работает в связке с модулем rlm_jradius для FreeRADIUS. Изначально он разработан Дэвидом Бёрдом (David Bird) во время работы над PicoPoint, B.V. В последствии разработка движка продолжилась и проект поддерживается по сей день.

JRadius - это не отдельный RADIUS-сервер, это Java-сервер, который вызывается rlm_jradius модулем, встроенным во FreeRADIUS. Модуль использует пул соединений с сервером JRadius и передаёт ему пакеты RADIUS-запроса и ответа для любого из событий которое в состоянии обработать любой из модулей FreeRADIUS. Это означает, что вы можете реализовать обработку событий аутентификации, авторизации и аккаунтинга через JRadius. Сам же сервер JRadius -это лёгкий выделенный сервер, конфигурирующийся через XML. Он позволяет использовать специфичный словарь JRadius/FreeRADIUS и любое число ваших собственных обработчиков составляющих единую цепочку (chained handlers).
Итак, я проникся идеей JRadius и загорелся желанием реализовать необходимую функциональность на его базе. Всё что мне пришлось для этого сделать - это скачать JRadius, включить его в проект, написать собственный обработчик (CADBiSHandler) и переопределить метод handle().
Работать с RADIUS-пакетами в JRadius - одно удовольствие. Например, чтобы получить какой-либо атрибут, нужно всего-лишь вызвать:
req.getAttributes().get("Client-IP-Address")
А если необходимо определить тип запроса и в зависимости от этого принять какое-то решение, то можно это реализовать так:
public boolean handle(JRadiusRequest jRequest)
{
  int type = jRequest.getType();
  switch (type)
  {
    case JRadiusServer.JRADIUS_accounting:
    {
      //...
    }
    break;
    case JRadiusServer.JRADIUS_authorize:
    {
      //...
    }
    break;
  }
}
В общем, повторить функциональность FreeNIBS труда не составило. Поэтому было решено реализовать что-нибудь поинтереснее.
Изначально, когда CADBiS только зарождалась, ситуация была следующей. Имелся некоторый ограниченный объём трафика, который было разрешено скачать в месяц(например, 20 гб). Необходимо было так поделить этот трафик между пользователями, чтобы во-первых каждая группа получила то количество, которое соответствует её статусу и числу человек, а во-вторых чтобы существовала некоторая дневная норма, превышение которой запрещено, для того чтобы как можно более рационально поделить месячный Интернет-трафик между пользователями. FreeNIBS этого сделать не позволяет, а реализовать это на нём было слишком сложно и лениво. Теперь же, с использованием JRadius эта идея должна была воплотиться в жизнь.
Идея в следующем. Задаётся месячный предел трафика, превышение которого невозможно. Каждой группе пользователей (будь то администраторы или же студенты) назначается определённое число баллов. В соответствии с этим числом пересчитывается максимальное количество трафика, которое они могут использовать в месяц. Зная текущее число месяца и количество дней в месяце, можно определить сколько дней с начала месяца прошло и сколько ещё остаётся. А значит, можно вычислить дневную норму трафика для каждой группы. Однако, разрешить пользователям определённой группы скачать фиксированное количество трафика в день недостаточно, т.к. кто-то может хотеть выкачать свою долю сегодня, а завтра не придёт вообще. Поэтому было решено разрешить превышения на несколько дней вперёд. То есть, к примеру, норма для студентов - 300 мегабайт за день. Система должна разрешить скачать им 300 мегабайт за текущий день, потом ещё 300 мегабайт за следующий день, и только потом отключить.
Подобная организация позволяет гибко управлять системой и лимитами трафика. Если какой-то группе не хватает их дневного лимита, а у другой группы лимит не расходуется и наполовину, всегда можно подменить баллы так, что каждый получит трафик в соответствии со своими потребностями, и при этом общий объём останется фиксированным.
Далее я расскажу про систему категоризации и фильтрации контента, и соовтетсвенно про прокси-сервер на Java.

Ярлыки: , , , , ,

пятница, 25 апреля 2008 г.

CADBiS начало...

Решил открыть серию постов посвящённых моему дипломному проекту. Проект представляет собой систему управления доступом в Интернет.
Акцент в проекте идёт не на расчёт стоимости потребляемых услуг и списание средств (или попросту говоря биллинг), а на специфику предприятия на котором данная система должна быть установлена, а именно - локальная сеть кафедры САПР, на которой я учусь.
Клиентами системы являются студенты, преподаватели, аспиранты и сотрудники. Каждая группа должна иметь собственные права и лимиты доступа. Так же необходимо создать систему управления контентом, который получают из Интернета пользователи, потому как по идее студенты должны расходовать Интернет-трафик исключительно в учебных целях, ровно как и преподаватели.
На сегодняшний день система успешно функционирует. Она основана на открытой биллинг-системе FreeNIBS, которая в свою очередь представляет собой модуль сервера аутентификации FreeRADIUS, являющегося на сегодняшний день одним из самых популярных RADIUS-серверов в сети. Установление соединений по протоколу pptp происходит с помощью сервера mpd. И крутится всё это дело на шлюзе под управлением FreeBSD.
Эта система была настроена, поставлена, к ней был разработан веб-интерфейс для администраторов. Код FreeNIBS был частично модифицирован и в него была добавлена функция работы с оповещениями пользователей. Так же был настроен и подключен прокси-сервер Squid, который позволил отфильтровать некоторые нежелательные веб-ресурсы. И всё это в рамках бакалаврского проекта.
В системе был лишь базовый функционал. Конечно, ни о каких фильтрах контента речи не было. Главным параметром являлся Интернет-трафик, и предполагалось что его верхний порог - вполне ограниченное число, а поэтому система должна была уметь распределить использование трафика как можно более рационально. Для этого в веб-интерфейсе была предусмотрена "система поддержки принятия решений", которая сообщала администратору о том, что в какой-либо из дней расход трафика превысил свою дневную норму. Что плохо? Система базировалась на FreeNIBS, а это как плюс так и минус. Минус в том, что код на языке C, отладить который можно лишь вкомпилив во FreeRADIUS, представляется абсолютно не-maintanable и не-extensible. На написание простейшей функции отправки уведомлений ушло несколько дней. Посему, данная часть была в последствии выделена в ядро и не модифицировалась по причине невероятной лени, возникающей при одной мысли об этом коде:)
Далее система расширялась при помощи написания собственного прозрачного proxy-сервера, который бы отслеживал посещаемые ресурсы, составлял протоколы и записывал в базу. Данный сервер был выбран без особых поисков - и им стал входивший в необновлённую версию портов FreeBSD 5.4 tproxy. Опять же пришлось писать ужасающий код на C. При этом, код был написан в лучших традициях классической UNIX-архитектуры и вместо использования POSIX-threads он реализовывал многозадачность при помощи fork (собственно, FreeRADIUS тоже её использовал, но нагрузка на него была в разы меньше). В результате чего сервер часто просто загибался от обилия процессов. К тому же запись логов в базу была реализована путём модифицирования кода tproxy и реализована в том же стиле, в результате чего на каждый пакет создавались процесс обработки запроса и процесс записи запроса в базу, и при этом (!) соединение с базой открывалось для каждого пакета!
Представить сейчас страшно, что я так мог написать. Естественно, что сервер умирал когда кто-то начинал что-то просто скачивать. Немного помогли шаманские пляски с sysctl (было увеличено максимальное число сокетов). Но в итоге от данной утилиты было решено отказаться.
Второй попыткой реализовать свой proxy было написание его с 0 на чистом C++. Здесь, разумеется всё было сделано уже умнее. Для многозадачности использовались потоки, для синхронизации - мьютексы, был реализован собственный потоковый пул (от POSIX-пула было решено отказаться по ряду причин) и всё работало прекрасно. Если бы не одно но. Память текла. А куда текла - было очень трудно понять. Учитывая моё неумение пользоваться средствами типа dbg и некоторую несовместимость кода с Windows-платформой, отладить момент утечки оказалось нереальным и эту ветку тоже пришлось заморозить.
Но вот пришло время когда до защиты магистерского диплома осталось всего пара месяцев. И неожиданно появилось желание реализовать proxy на Java, особенно после нескольких пробных попыток и оценки кроссплатформенности. И ведь действительно, данный проект оказался в итоге наиболее перспективным...

[To be continued]

Ярлыки: , , , , , , ,

-->