Биллинговая система Nodeny
16 Сентября 2021, 20:40:56 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Прекращена поддержка версии Nodeny 49
 
   Начало   Помощь Поиск Войти Регистрация  
Страниц: [1]
  Печать  
Автор Тема: rev 549. Модуль ядра ses_traf  (Прочитано 4213 раз)
Efendy
Администратор
Спец
*****

Карма: 137
Offline Offline

Сообщений: 4714



Просмотр профиля
« : 24 Декабря 2018, 16:12:56 »

В 14 году я показал как можно собирать трафик не через коллекторы (ip/netflow и т.д), а через аккаунтинг радиуса: http://forum.nodeny.com.ua/index.php?topic=2495.0

Эта фича интересна тем, что аккаунтинг как раз и предназначен для сбора трафика, а то, что мы используем его как продление авторизации - это побочный бонус. Таким образом, раз данные о трафике к нам приходят - значит не надо тратить ресурсы на их подсчет модулем collectors. Конечно, у нас не будет данных по детализации (на какие ip были запросы), но многим она и не нужна.

В чем сложность считать трафик через аккаунтинг? Дело в том, что радиус присылает нам общий трафик на сессию, а не то, сколько скачал абонент за последний срез. Допустим в 10:41 радиус прислал 100 мб, а в 10:42 - 101 мб. Таким образом, биллинг должен увеличить счетчики трафика на 1 мб (101 - 100). Следовательно, нужно где-то хранить данные трафика за предыдущий срез. Для этого и была придумана таблица ses_traf.

Но как оказалось, при большом количестве запросов mysql начинает жестко тупить. Поэтому то, что написано по ссылке выше, уже не будем использовать. А слегка поменяем схему. Теперь в аккаунтинге процедуры mysql просто будут писать текущие значения трафика, а начислять трафик будет модуль ядра ses_traf.

Необходимо немного поменять структуру таблицы ses_traf:

Код:
DROP TABLE ses_traf;
CREATE TABLE `ses_traf` (
  `id` bigint(21) NOT NULL AUTO_INCREMENT,
  `uid` int(10) unsigned NOT NULL,
  `ses_id` varchar(32) NOT NULL DEFAULT '',
  `time` int(10) unsigned NOT NULL DEFAULT '0',
  `traf_in` bigint(12) unsigned NOT NULL DEFAULT '0',
  `traf_out` bigint(12) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `time` (`time`)
) ENGINE=MyISAM AUTO_INCREMENT=1;

По сути в нее внесли 2 изменения: добавили поле uid (id абона) и убрали уникальность ses_id - теперь эта таблица хранит не последние данные по трафику, а по сути лог трафика, но лог с накоплением трафика, который требует обработки модулем ses_traf.

Чтобы данные попадали в таблицу ses_traf, нужно изменить процедуру радиуса radupdate, примерно так:

Код:
CREATE DEFINER=`root`@`localhost` PROCEDURE `radupdate`(IN login VARCHAR(64), IN ip VARCHAR(16),
    IN properties VARCHAR(255), IN ses VARCHAR(32), IN trafin BIGINT(20), IN trafout BIGINT(20))
BEGIN
  DECLARE usr_id INT;
  DECLARE usr_ip VARCHAR(15) DEFAULT NULL;
  SELECT id INTO usr_id FROM users WHERE name=login LIMIT 1;
  SELECT get_ip(usr_id) INTO usr_ip;
  CALL set_auth(usr_ip, CONCAT('mod=pppoe;',REPLACE(properties,':','')));
  INSERT INTO ses_traf SET ses_id=ses, traf_in=trafin, traf_out=trafout, time=UNIX_TIMESTAMP(), uid=usr_id;
END

По сути в параметры процедуры добавлено 3 параметра: сессия, входящий и исходящий трафик + строка:

Код:
INSERT INTO ses_traf SET ses_id=ses, traf_in=trafin, traf_out=trafout, time=UNIX_TIMESTAMP(), uid=usr_id;
Кстати, привязка работает именно к сессии. У клиента может быть несколько сессий с разным трафиком.

Создание X-таблицы для лога трафика NoDeny не нужно - это также делается в модуле ses_traf.

Конфиг радиуса:

Код:
    authorize_check_query = "call radcheck('%{User-Name}')"
        authorize_reply_query = "call radreply('%{User-Name}')"
        accounting {
            query = "call radupdate('%{User-Name}','%{Framed-IP-Address}',\
                    'user=%{Calling-Station-Id};nas=%{NAS-IP-Address};ses=%{Acct-Session-Id}','%{Acct-Session-Id}',\
            (%{%{Acct-Input-Gigawords}:-0} * POWER(2, 32)) + %{%{Acct-Input-Octets}:-0},\
            (%{%{Acct-Output-Gigawords}:-0} * POWER(2, 32)) + %{%{Acct-Output-Octets}:-0})"
            type {
                start {
                    query = "call radupdate('%{User-Name}','%{Framed-IP-Address}',\
                            'user=%{Calling-Station-Id};nas=%{NAS-IP-Address};ses=%{Acct-Session-Id}','%{Acct-Session-Id}',\
                (%{%{Acct-Input-Gigawords}:-0} * POWER(2, 32)) + %{%{Acct-Input-Octets}:-0},\
                (%{%{Acct-Output-Gigawords}:-0} * POWER(2, 32)) + %{%{Acct-Output-Octets}:-0})"
                }
            }
        }
       
    accounting_update_query = "call radupdate('%{User-Name}','%{Framed-IP-Address}',\
            'user=%{Calling-Station-Id};nas=%{NAS-IP-Address};ses=%{Acct-Session-Id}','%{Acct-Session-Id}',\
            (%{%{Acct-Input-Gigawords}:-0} * POWER(2, 32)) + %{%{Acct-Input-Octets}:-0},\
            (%{%{Acct-Output-Gigawords}:-0} * POWER(2, 32)) + %{%{Acct-Output-Octets}:-0})"

Запускаем модуль ядра ses_traf и наслаждаемся.
Записан
WideAreaNetwork
Старожил
****

Карма: 1
Offline Offline

Сообщений: 283


Просмотр профиля Email
« Ответ #1 : 24 Декабря 2018, 17:10:39 »

Цитировать
Конечно, у нас не будет данных по детализации (на какие ip были запросы), но многим она и не нужна.
вопрос времени, блеклисты уже есть, потом аппаратный фаервол (аля умирают все маленькие провы), ну и вдобавок хранение истории по каждому абону, только не понятно сколько времени захотят, 3-6 месяцев или 1-3года
Записан
Cell
NoDeny
Спец
*

Карма: 51
Offline Offline

Сообщений: 1424



Просмотр профиля
« Ответ #2 : 24 Декабря 2018, 23:30:06 »

В любом случае это не средствами биллинга должно делаться. Если уж на то пошло, есть специальная аппаратура СОРМ в которой все  это предусмотрено с учетом скоростных нагрузок (всякие кольцевые буферы, массивы данных и тп.)
Записан
k291
Старожил
****

Карма: -10
Offline Offline

Сообщений: 443


Просмотр профиля
« Ответ #3 : 26 Декабря 2018, 19:18:30 »

Попробовал в связке с Mikrotik`ом, радиус перестал выдавать ip.

mysql -uroot -p
use nodeny;
Код:
DROP TABLE ses_traf;
CREATE TABLE `ses_traf` (
  `id` bigint(21) NOT NULL AUTO_INCREMENT,
  `uid` int(10) unsigned NOT NULL,
  `ses_id` varchar(32) NOT NULL DEFAULT '',
  `time` int(10) unsigned NOT NULL DEFAULT '0',
  `traf_in` bigint(12) unsigned NOT NULL DEFAULT '0',
  `traf_out` bigint(12) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `time` (`time`)
) ENGINE=MyISAM AUTO_INCREMENT=1;

Код:
DROP PROCEDURE IF EXISTS `radupdate`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `radupdate`(IN login VARCHAR(64), IN ip VARCHAR(16),
    IN properties VARCHAR(255), IN ses VARCHAR(32), IN trafin BIGINT(20), IN trafout BIGINT(20))
BEGIN
  DECLARE usr_id INT;
  DECLARE usr_ip VARCHAR(15) DEFAULT NULL;
  SELECT id INTO usr_id FROM users WHERE name=login LIMIT 1;
  SELECT get_ip(usr_id) INTO usr_ip;
  CALL set_auth(usr_ip, CONCAT('mod=pppoe;',REPLACE(properties,':','')));
  INSERT INTO ses_traf SET ses_id=ses, traf_in=trafin, traf_out=trafout, time=UNIX_TIMESTAMP(), uid=usr_id;
END$$
DELIMITER ;
quit:


nano /etc/freeradius/sql.conf
Тект из "Конфиг радиуса:", предварительно закоментировав:
Цитировать
        authorize_check_query = "call radcheck('%{User-Name}')"
        authorize_reply_query = "call radreply('%{User-Name}', '%{Called-Station-Id}')"
        postauth_query = "call radupdate('%{User-Name}','%{reply:Framed-IP-Address}','nas=%{NAS-IP-Address}', '%{Called-Station-Id}')"
        accounting_update_query = "call radupdate('%{User-Name}','%{Framed-IP-Address}','nas=%{NAS-IP-Address}', '%{Called-Station-Id}')"

/etc/init.d/freeradius restart


В итоге в логе Микротика -"dhcp_1_sp: radius authentication failed for 00:.......:B2: access rejected"


Вернул все как было, кроме таблицы ses_traf
Записан
Efendy
Администратор
Спец
*****

Карма: 137
Offline Offline

Сообщений: 4714



Просмотр профиля
« Ответ #4 : 05 Января 2019, 12:19:10 »

видно, что authorize_reply_query принимает разное количество параметров в твоем и моем варианте. Так получилось, что стоят разные требования в разных сетях, поэтому радиус процедуры отличаются для разных ситуаций. Не нужно бездумно копировать, можно ж вникнуть сначала
Записан
Groov
NoDeny
Постоялец
*

Карма: -3
Offline Offline

Сообщений: 100

102196993
Просмотр профиля
« Ответ #5 : 25 Марта 2019, 10:13:03 »

Неправильно стал отображать "График трафика". Это только у меня Непонимающий
Записан
NodenY45
NoDeny
Старожил
*

Карма: 2
Offline Offline

Сообщений: 364


Просмотр профиля
« Ответ #6 : 25 Марта 2019, 18:39:30 »

Неправильно стал отображать "График трафика". Это только у меня Непонимающий


А конкретней? как неправильно? после каких действий?
Записан
fet4
Старожил
****

Карма: 2
Offline Offline

Сообщений: 321


Просмотр профиля Email
« Ответ #7 : 30 Апреля 2019, 20:22:33 »

Пока не в курил ses_traf.pm, не пойму нужно ли менять my $round_seconds = 60, если период аккаунтинга != 60 ?

И что бы не дублировать одни и те же call radupdate можно так

Код:
 accounting {
    reference = "%{tolower:type.%{Acct-Status-Type}.query}"

   type {

      start {
        query = "call radupdate(\
                '%{Framed-IP-Address}',\
                '%{Acct-Session-Id}',\
                '%{expr:(%{%{Acct-Input-Gigawords}:-0} * 4294967296) + %{%{Acct-Input-Octets}:-0}}',\
                '%{expr:(%{%{Acct-Output-Gigawords}:-0} * 4294967296) + %{%{Acct-Output-Octets}:-0}}',\
                'user=%{Calling-Station-Id};\
                nas=%{NAS-IP-Address};'\
                )"
      }

      stop {
        query = "call radstop('%{Framed-IP-Address}')"
      }

      interim-update {
        query = "${..start.query}"
      }

    }
  }
Записан
Efendy
Администратор
Спец
*****

Карма: 137
Offline Offline

Сообщений: 4714



Просмотр профиля
« Ответ #8 : 30 Апреля 2019, 22:12:18 »

Пока не в курил ses_traf.pm, не пойму нужно ли менять my $round_seconds = 60, если период аккаунтинга != 60 ?
если больше 60, то я бы поставил 60, если меньше 60, я бы не юзал round_seconds, хотя можно
Записан
fet4
Старожил
****

Карма: 2
Offline Offline

Сообщений: 321


Просмотр профиля Email
« Ответ #9 : 01 Мая 2019, 10:55:52 »

У меня аккаунтинг 300, правильно ли я понимаю что график трафика в течении этих 300 сек будет просто одинаковым до обновления, ses_traf просто будет считать что трафика не поменялся ?
Записан
fet4
Старожил
****

Карма: 2
Offline Offline

Сообщений: 321


Просмотр профиля Email
« Ответ #10 : 02 Апреля 2020, 22:31:41 »

По хорошему traf_in нужно записывать в traf_out или как-то реверсом выводить значения в админке и не только, иначе по отношению к клиенту значения перевернутые, с радиуса снимаются данные относительно интерфейса сервера.
Скрин в Гб,
Записан
Efendy
Администратор
Спец
*****

Карма: 137
Offline Offline

Сообщений: 4714



Просмотр профиля
« Ответ #11 : 03 Апреля 2020, 08:30:59 »

так в конфиге радиуса поменяй местами параметры
Записан
Страниц: [1]
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.20 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!