Биллинговая система Nodeny
25 Апреля 2024, 12:38:05 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Прекращена поддержка версии Nodeny 49
 
   Начало   Помощь Поиск Войти Регистрация  
Страниц: 1 2 [3] 4
  Печать  
Автор Тема: Deadlock-и, дубликаты ip и прочая хрень  (Прочитано 15540 раз)
fet4
Старожил
****

Карма: 2
Offline Offline

Сообщений: 324


Просмотр профиля Email
« Ответ #30 : 26 Февраля 2018, 19:04:14 »

Код:
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` PROCEDURE `radcheck_ipoe`(IN login VARCHAR(64))
BEGIN
  SELECT Null, login, 'Cleartext-Password' AS Attribute, '' AS Value,':=';
END$$
DELIMITER ;
Код:
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` PROCEDURE `radcheck_pppoe`(IN login VARCHAR(64))
BEGIN
  SELECT id,name,'Cleartext-Password' AS Attribute,AES_DECRYPT(passwd,'LroCmnvGELVXn2Vj') AS Value,':='
    FROM users WHERE name=login;
END$$
DELIMITER ;
Код:
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` PROCEDURE `radreply_ipoe`(IN `login` VARCHAR(64), IN `tag` VARCHAR(64))
BEGIN
DECLARE rad_mac VARCHAR(12);
    DECLARE rad_dev_mac VARCHAR(12);
    DECLARE rad_port VARCHAR(12);
    DECLARE usr_id INT;
DECLARE usr_ip VARCHAR(15);
    DECLARE usr_onecon INT;
DECLARE usr_onedev INT;
   
SELECT SUBSTRING_INDEX(login, '-', 1) INTO rad_mac;
    SELECT SUBSTRING_INDEX(login, '-', -1) INTO rad_port;
    SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(login, '-', 2), '-', -1) INTO rad_dev_mac;
   
    SELECT uid, oneconnect, onedevice INTO usr_id, usr_onecon, usr_onedev FROM mac_uid
WHERE device_mac=rad_dev_mac
    AND (device_port=rad_port OR (onedevice>0 AND device_mac<>''))
AND (mac=rad_mac OR (oneconnect>0 AND device_mac<>''))
        LIMIT 1;

IF usr_id IS NOT NULL AND usr_id > 0 THEN

SELECT get_ip_by_tag(usr_id, tag) INTO usr_ip;
UPDATE mac_uid SET ip=0 WHERE ip=INET_ATON(usr_ip) AND uid<>usr_id;
UPDATE mac_uid SET ip=INET_ATON(usr_ip), time=UNIX_TIMESTAMP() WHERE uid=usr_id;

IF usr_onecon > 0 OR usr_onedev > 0 THEN
            UPDATE mac_uid SET mac=NULL WHERE mac=rad_mac AND (oneconnect=0 OR onedevice=0);
            UPDATE mac_uid SET mac=rad_mac, device_port=rad_port WHERE device_mac=rad_dev_mac
AND (onedevice>0 OR (device_port=rad_port AND oneconnect>0));
        END IF;

    ELSE

        UPDATE mac_uid SET ip=0 WHERE uid=0 AND time<(UNIX_TIMESTAMP()-3600);
        UPDATE mac_uid SET mac=NULL WHERE mac=rad_mac AND (oneconnect>0 OR onedevice>0);

        START TRANSACTION;
        SELECT INET_NTOA(ip) INTO usr_ip FROM ip_pool p WHERE uid=0 AND type='dynamic'
AND tags LIKE CONCAT('%,', tag ,',%')
AND NOT EXISTS (SELECT ip FROM mac_uid WHERE ip=p.ip)
ORDER BY RAND() LIMIT 1 FOR UPDATE;

        INSERT INTO mac_uid VALUES(
            NULL, rad_mac, INET_ATON(usr_ip), 0, UNIX_TIMESTAMP(), rad_dev_mac, rad_port, 0, 0)
        ON DUPLICATE KEY
            UPDATE ip=IF(ip>0 AND device_mac=rad_dev_mac AND device_port=rad_port, ip, INET_ATON(usr_ip)),
uid=0, device_mac=rad_dev_mac, device_port=rad_port, time=UNIX_TIMESTAMP();
        COMMIT;

        SELECT INET_NTOA(ip) INTO usr_ip FROM mac_uid
WHERE mac=rad_mac AND device_mac=rad_dev_mac AND device_port=rad_port;

    END IF;

    SELECT NULL, login, 'Framed-IP-Address', usr_ip, '=';

END$$
DELIMITER ;
Код:
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` PROCEDURE `radreply_pppoe`(IN `login` VARCHAR(64), IN `tag` VARCHAR(64))
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_by_tag(usr_id, tag) INTO usr_ip;

  SELECT NULL,login,'Framed-IP-Address',usr_ip,'=';
  SELECT NULL,login,'Framed-IP-Netmask','255.255.255.255','=';
  SELECT NULL,login,'Framed-Protocol','PPP','=';
 
END$$
DELIMITER ;
Код:
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` PROCEDURE `radupdate_ipoe`(IN `login` VARCHAR(64), IN `ipa` VARCHAR(16),
IN `properties` VARCHAR(255), IN `tag` VARCHAR(64), IN `ses` VARCHAR(64))
BEGIN
DECLARE rad_mac VARCHAR(12);
    DECLARE rad_dev_mac VARCHAR(12);
    DECLARE rad_port VARCHAR(12);
    DECLARE usr_id INT;
    DECLARE usr_ip VARCHAR(15);
   
    SELECT SUBSTRING_INDEX(login, '-', 1) INTO rad_mac;
    SELECT SUBSTRING_INDEX(login, '-', -1) INTO rad_port;
    SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(login, '-', 2), '-', -1) INTO rad_dev_mac;
 
    SELECT uid INTO usr_id FROM mac_uid WHERE device_mac=rad_dev_mac
    AND (device_port=rad_port OR (onedevice>0 AND device_mac<>''))
AND (mac=rad_mac OR (oneconnect>0 AND device_mac<>''))
        LIMIT 1;

    IF usr_id IS NULL THEN
        SELECT ipa INTO usr_ip;
    ELSE
        SELECT get_ip_by_tag(usr_id, tag) INTO usr_ip;
    END IF;

    CALL set_auth(usr_ip, CONCAT('mod=dhcp;user=', rad_mac, ';', 'dev=', rad_dev_mac, ';', 'port=', rad_port, ';',
'ses=', ses, ';', REPLACE(properties,':','')));
UPDATE mac_uid SET time=UNIX_TIMESTAMP() WHERE ip=INET_ATON(ipa) LIMIT 1;
END$$
DELIMITER ;
Код:
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` PROCEDURE `radupdate_pppoe`(IN `login` VARCHAR(64), IN `ip` VARCHAR(16), IN `properties` VARCHAR(255), IN `tag` VARCHAR(64), IN `ses` VARCHAR(64))
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_by_tag(usr_id, tag) INTO usr_ip;
  CALL set_auth(usr_ip, CONCAT('mod=pppoe;','ses=',ses,';',REPLACE(properties,':','')));
END$$
DELIMITER ;
Код:
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` PROCEDURE `set_auth`(IN `usr_ip` VARCHAR(15), IN `auth_properties` VARCHAR(255))
BEGIN
  DECLARE usr_id INT;
  SELECT uid INTO usr_id FROM ip_pool WHERE INET_ATON(usr_ip) = ip LIMIT 1;

  IF( usr_id > 0 ) THEN

    INSERT INTO auth_now SET
        ip = usr_ip,
        properties = auth_properties,
        start = UNIX_TIMESTAMP(),
        last = UNIX_TIMESTAMP()
    ON DUPLICATE KEY UPDATE
        properties = IF(auth_properties!='',auth_properties,properties),
        last = UNIX_TIMESTAMP();

    UPDATE ip_pool SET `release` = UNIX_TIMESTAMP() + 3600
        WHERE ip = INET_ATON(usr_ip) LIMIT 1;
  END IF;
END$$
DELIMITER ;
Код:
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` FUNCTION `get_ip_by_tag`( user_id INTEGER UNSIGNED, tag VARCHAR(64) ) RETURNS varchar(15) CHARSET utf8
    NO SQL
BEGIN
    DECLARE user_ip VARCHAR(15);
    DECLARE real_ip VARCHAR(15) DEFAULT 0;
    DECLARE row_cnt INTEGER;
    DECLARE ip_id INTEGER;
    DECLARE tries INTEGER DEFAULT 30;
    DECLARE id_min INTEGER;
    DECLARE id_max INTEGER;

    SELECT INET_NTOA(ip) INTO user_ip FROM ip_pool
        WHERE uid = user_id AND type='static' LIMIT 1;
    IF( user_ip IS NOT NULL ) THEN RETURN user_ip; END IF;

    SELECT 1 INTO real_ip FROM users_services WHERE uid = user_id AND tags LIKE '%,realip,%';

    SELECT id, INET_NTOA(ip) INTO ip_id, user_ip FROM ip_pool
        WHERE uid = user_id AND type = 'dynamic' AND realip = IF(real_ip>0,1,0)
            AND tags LIKE CONCAT('%,', tag, ',%')
        LIMIT 1;

    IF( ip_id IS NOT NULL) THEN
        UPDATE ip_pool SET `release` = UNIX_TIMESTAMP() + 3600
            WHERE id = ip_id AND uid = user_id;
        SELECT ROW_COUNT() INTO row_cnt;
        IF( row_cnt > 0 ) THEN RETURN user_ip; END IF;
    END IF;

    SELECT MAX(id), MIN(id) INTO id_max, id_min
        FROM ip_pool
        WHERE type = 'dynamic' AND realip = IF(real_ip>0,1,0)
            AND tags LIKE CONCAT('%,', tag, ',%');

    sel_ip: WHILE tries > 0 DO
        SELECT id, INET_NTOA(ip) INTO ip_id, user_ip
            FROM ip_pool
            WHERE uid = 0
                AND id >= (CEIL(RAND() * (id_max - id_min)) + id_min)
                AND id <= id_max
                LIMIT 1;
        IF( user_ip IS NOT NULL) THEN
            UPDATE ip_pool SET uid = user_id, `release` = UNIX_TIMESTAMP() + 3600
                WHERE id = ip_id AND uid = 0;
            SELECT ROW_COUNT() INTO row_cnt;
            IF( row_cnt > 0 ) THEN RETURN user_ip; END IF;
            SET tries = tries - 5;
        END IF;
        SET tries = tries - 1;
    END WHILE;

END$$
DELIMITER ;
Код:
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` FUNCTION `normalize_ippool`() RETURNS tinyint(4)
    NO SQL
BEGIN
    DECLARE mid INTEGER UNSIGNED;

    CREATE TEMPORARY TABLE temp_ip_pool(
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        ip_id BIGINT UNSIGNED NOT NULL,
        PRIMARY KEY (id)
    );

    SELECT MAX(id) into mid FROM ip_pool;
    UPDATE ip_pool SET id = id + mid;
    INSERT temp_ip_pool (SELECT NULL, id FROM ip_pool ORDER BY realip, type, tags);
    UPDATE ip_pool i JOIN temp_ip_pool t ON i.id = t.ip_id SET i.id = t.id;
    DROP TEMPORARY TABLE IF EXISTS temp_ip_pool;

    RETURN 1;
END$$
DELIMITER ;
Записан
Efendy
Администратор
Спец
*****

Карма: 138
Offline Offline

Сообщений: 4782



Просмотр профиля
« Ответ #31 : 26 Февраля 2018, 21:29:08 »

Трудно так сразу сказать где проблема. Тебе нужно сделать предварительное расследование. Взять конкретный случай и проанализировать ситуацию по логам и биллинга и радуиуса и т.д.
Записан
kosmich
Пользователь
**

Карма: 1
Offline Offline

Сообщений: 90


Просмотр профиля
« Ответ #32 : 26 Февраля 2018, 21:55:02 »

в процедурах у меня мало опыта, но вижу что похоже ты пошел своим путем с процедурами.
По крайней мере с `radupdate_pppoe` как советовал Стас, ты не сделал, а решил другим путем.
В соседней теме, после удаления одного параметра, у меня выдавался левый айпи абоненту, хотя в админке показывало онлайн и статику.
Какие еще могут быть глюки, учитывая что у тебя достаточно навернуто, неизвестно.
Сделал бы на стенде, процедуры из документации без тегов, с добавлением параметра для корректной работы "статики" пппое.
Добавил тег, дальше пошагово изменяя под себя процедуры.
И смотреть на чем начинаются глюки.
Можно конечно и с текущими пытаться разбираться, если абонов не жалко. Улыбающийся
Записан
fet4
Старожил
****

Карма: 2
Offline Offline

Сообщений: 324


Просмотр профиля Email
« Ответ #33 : 27 Февраля 2018, 13:23:39 »

Кажется я понял в чем проблема.

Судя по логике биллинга, при выдаче ip, get_ip_by_tag и не только ориентируется на занятость ip по uid=0, если равно 0 то Ip свободен и это работало и работает с pppoe и другими тоннелями когда ip выдается исключительно клиенту в базе.

И тут приходит dhcp через radius. Создавая логику авторизации клиента по dhcp мы понимаем что теперь нужно всем отвечать ACCEPT и выдавать ip с пула, чтобы в дальнейшем клиент мог авторизовать свое подключение и привязаться к учетной записи самостоятельно. И тут всплывает один нюанс.

Вызывая radreply_ipoe
Цитировать
IF usr_id IS NOT NULL AND usr_id > 0 ELSE

Мы тупо берем и выдаем ip у кого uid=0 и даже не помечаем, никак что мы его выдали.
Код:
SELECT INET_NTOA(ip) INTO usr_ip FROM ip_pool p WHERE uid=0 AND type='dynamic'
AND tags LIKE CONCAT('%,', tag ,',%')
AND NOT EXISTS (SELECT ip FROM mac_uid WHERE ip=p.ip)
ORDER BY RAND() LIMIT 1 FOR UPDATE;

В get_ip_by_Tag примерно так же происходит выборка по uid=0

Это не создаст больших проблем, если клиент следом авторизует свое подключение но имеется много случаев когда ip выдается просто на устройство которое не авторизуется долгое время и тупо весит, допустим на сетевую карту компьютера на котором пока используется pppoe.

И даже если создать отдельный пул в биллинге для вот таких гостевых подключений, они все так же не будут фиксироваться что выдавались какому-то устройству и будет вероятность что уже выданный Ip снова кто-то получит.

Как по мне, то нужно менять логику выдачи ip и фиксировать выданные как-то по другому но не uid<>0, в связи с тем что ppp на сегодняшний день становится не единственным типом подключения.

Так оно и получается у меня на сегодняшний момент, я фиксирую дубликаты как раз у не авторизованных устройств и клиентов. Дубликатов у двух клиентов я не встречал пока.

Цитировать
По крайней мере с `radupdate_pppoe` как советовал Стас, ты не сделал, а решил другим путем.
Напомни как он советовал.
Записан
kosmich
Пользователь
**

Карма: 1
Offline Offline

Сообщений: 90


Просмотр профиля
« Ответ #34 : 27 Февраля 2018, 15:34:57 »

Напомни как он советовал.
Взять процедуры дхцп и пппое из мануала и добавить в пппое строку UPDATE users SET id=usr_id WHERE id=usr_id LIMIT 1;

Код:
DROP PROCEDURE IF EXISTS `radupdate`;
DELIMITER $$
CREATE PROCEDURE `radupdate`(IN login VARCHAR(64), IN ip VARCHAR(16), IN properties VARCHAR(255))
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,':','')));
  UPDATE users SET id=usr_id WHERE id=usr_id LIMIT 1;
END$$
DELIMITER ;

Так оно и получается у меня на сегодняшний момент, я фиксирую дубликаты как раз у не авторизованных устройств и клиентов. Дубликатов у двух клиентов я не встречал пока.
Вот, поэтому у тебя и не "дубли". Улыбающийся
У меня у авторизованных абонентов дубли были, до решения описанного в первых постах в теме.
У меня пулы, для дхцп и пппое разные, описанных тобой проблем, пока не наблюдал.

Как по мне, то нужно менять логику выдачи ip и фиксировать выданные как-то по другому но не uid<>0, в связи с тем что ppp на сегодняшний день становится не единственным типом подключения.
Может не менять логику а просто сделать два разных пула ? И тогда дхцп сервер, не сможет выдать айпи который уже выдан пппое или не авторизованному абоненту.
Не припомню такого, чтоб дхцп сервер, выдавал одинаковые айпи двум разным абонентам.

Не твой вариант ?
h t t p://forum.nodeny.com.ua/index.php?topic=2441.msg24632#msg24632
Суть в чем - апдейтим авторизацию по фактическому ip-адресу сессии клиента, а не по выборке из get_ip
« Последнее редактирование: 27 Февраля 2018, 15:59:02 от kosmich » Записан
fet4
Старожил
****

Карма: 2
Offline Offline

Сообщений: 324


Просмотр профиля Email
« Ответ #35 : 27 Февраля 2018, 19:37:07 »

Код:
UPDATE users SET id=usr_id WHERE id=usr_id LIMIT 1;
это бессмысленный запрос, я по другому поступил.

Цитировать
У меня пулы, для дхцп и пппое разные, описанных тобой проблем, пока не наблюдал.
dhcp у тебя надеюсь через radius?

Цитировать
Может не менять логику а просто сделать два разных пула ? И тогда дхцп сервер, не сможет выдать айпи который уже выдан пппое или не авторизованному абоненту.
Ты пойми дело не в пулах, даже если создам отдельный для dhcp пул все равно будет вероятность что ip получит кто-то другой с этого же пула, так как когда ip выдается гостю, то в ip_pool это никак не фиксируется.
Записан
Efendy
Администратор
Спец
*****

Карма: 138
Offline Offline

Сообщений: 4782



Просмотр профиля
« Ответ #36 : 28 Февраля 2018, 06:43:00 »

Не фиксируется в ip_pool, зато фиксируется в mac_uid, что данная комбинация параметров авторизации уже связана с таким-то ip. Но при беглом вгляде, ты этот код просто выкинул из процедуры
Записан
fet4
Старожил
****

Карма: 2
Offline Offline

Сообщений: 324


Просмотр профиля Email
« Ответ #37 : 28 Февраля 2018, 12:33:12 »

Ничего не выкинуто. Я так понимаю ты об этом говоришь? это есть в radreply
Цитировать
SELECT INET_NTOA(ip) INTO usr_ip FROM ip_pool p WHERE uid=0 AND type='dynamic'
         AND tags LIKE CONCAT('%,', tag ,',%')
         AND NOT EXISTS (SELECT ip FROM mac_uid WHERE ip=p.ip)
         ORDER BY RAND() LIMIT 1 FOR UPDATE;

Цитировать
AND NOT EXISTS (SELECT ip FROM mac_uid WHERE ip=p.ip)
это выполняется если usr_id = 0

если uid > 0 вызывается get_ip_by_tag в которой скорей всего так же нужно добавить эту проверку, что-то типа
Цитировать
sel_ip: WHILE tries > 0 DO
        SELECT id, INET_NTOA(ip) INTO ip_id, user_ip
            FROM ip_pool
            WHERE uid = 0
                AND id >= (CEIL(RAND() * (id_max - id_min)) + id_min)
                AND id <= id_max
                AND NOT EXISTS (SELECT ip FROM mac_uid WHERE ip=p.ip)
                LIMIT 1;

Но тут возникает другой вопрос, кто очищает ip в mac_uid по истечению авторизации и срока аренды?
Записан
Efendy
Администратор
Спец
*****

Карма: 138
Offline Offline

Сообщений: 4782



Просмотр профиля
« Ответ #38 : 28 Февраля 2018, 13:40:26 »

Но тут возникает другой вопрос, кто очищает ip в mac_uid по истечению авторизации и срока аренды?
В radreply: UPDATE mac_uid SET ip=0 WHERE uid=0 AND time<(UNIX_TIMESTAMP()-3600);

Кстати, в этом может и быть проблема ибо при аккаунтинге вызывает только set_auth и там не модифицируется время в mac_uid, ну или это делать в radreply непосредственно
Записан
fet4
Старожил
****

Карма: 2
Offline Offline

Сообщений: 324


Просмотр профиля Email
« Ответ #39 : 28 Февраля 2018, 13:59:15 »

Так что добавлять
 AND NOT EXISTS (SELECT ip FROM mac_uid WHERE ip=p.ip)

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

Карма: 138
Offline Offline

Сообщений: 4782



Просмотр профиля
« Ответ #40 : 28 Февраля 2018, 15:19:25 »

Невнимательно читаешь.  У нас есть таблица mac_uid, которая выполняет 2 функции:
1) хранит связки мак = id абона (в данном случае проблема не в этом варианте)
2) хранит связки ip = время, когда мы последний раз проверяли, что данный ip был кому-то выдан

Т.е. работает так: неизвестный абон подсоединился, мы выдали ему любой свободный ip, при этом запомнили в mac_uid, что данный ip уже выдан. При этом установили время. Теперь следующий неизвестный абон подконнектился и мы выбираем свободный ip из ip_pool, но при этом проверяем, что в mac_uid нет этого ip.

Схема рабочая? Нет. Потому, что у нас рано или поздно закончатся все ip, потому что они все попадут в mac_uid. Поэтому в процедуре radreply у нас проиcходит удаление таких ip:
Код:
UPDATE mac_uid SET ip=0 WHERE uid=0 AND time<(UNIX_TIMESTAMP()-3600)
Другими словами мы стерли ip (вместо него записали 0) у которого время попадания в таблицу mac_uid было больше часа назад.

А если неизвестный абон висит не час, а сутки? Хреново: ибо ip через час исчезнет из mac_uid, а по сути им занят. Поэтому не хватает малости: при каждом аккаунтинге неизвестного абона нужно поле time устанавливать в текущее время
Записан
fet4
Старожил
****

Карма: 2
Offline Offline

Сообщений: 324


Просмотр профиля Email
« Ответ #41 : 28 Февраля 2018, 19:10:04 »

Стас! Со всем последним тобою сказанным согласен! И обновление time так же происходит  в radupdate
Цитировать
DELIMITER $$
CREATE DEFINER=`nodeny`@`%` PROCEDURE `radupdate_ipoe`(IN `login` VARCHAR(64), IN `ipa` VARCHAR(16),
   IN `properties` VARCHAR(255), IN `tag` VARCHAR(64), IN `ses` VARCHAR(64))
BEGIN
   DECLARE rad_mac VARCHAR(12);
    DECLARE rad_dev_mac VARCHAR(12);
    DECLARE rad_port VARCHAR(12);
    DECLARE usr_id INT;
    DECLARE usr_ip VARCHAR(15);
    
    SELECT SUBSTRING_INDEX(login, '-', 1) INTO rad_mac;
    SELECT SUBSTRING_INDEX(login, '-', -1) INTO rad_port;
    SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(login, '-', 2), '-', -1) INTO rad_dev_mac;
  
    SELECT uid INTO usr_id FROM mac_uid WHERE device_mac=rad_dev_mac
          AND (device_port=rad_port OR (onedevice>0 AND device_mac<>''))
         AND (mac=rad_mac OR (oneconnect>0 AND device_mac<>''))
              LIMIT 1;
            
    IF usr_id IS NULL THEN
        SELECT ipa INTO usr_ip;
    ELSE
        SELECT get_ip_by_tag(usr_id, tag) INTO usr_ip;
    END IF;
   
    CALL set_auth(usr_ip, CONCAT('mod=dhcp;user=', rad_mac, ';', 'dev=', rad_dev_mac, ';', 'port=', rad_port, ';',
      'ses=', ses, ';', REPLACE(properties,':','')));
   UPDATE mac_uid SET time=UNIX_TIMESTAMP() WHERE ip=INET_ATON(ipa) LIMIT 1;
END$$
DELIMITER ;

НО

Подключается наш клиент, не гость и у него динамика и ip уже его освободился который был в предыдущей сессии и тут он запрашивает новый ip с пула. Что происходит? Вызывается get_ip_by_tag в котором происходит выборка свободного ip, без проверки что в mac_uid нет этого ip и тут появляется вероятность что вполне законный клиент может получить ip который есть уже в mac_uid у гостя и при выдаче гостю этот ip никак не по метился в ip_pools

Потом, запросов radreply от гостей в какой-то момент может не быть, следовательно Ip по таймауту не сброситься, как по мне правильней бы, этот вызов вынести допустим в модуль ядра dhcp
Код:
UPDATE mac_uid SET ip=0 WHERE uid=0 AND time<(UNIX_TIMESTAMP()-3600);
Записан
Efendy
Администратор
Спец
*****

Карма: 138
Offline Offline

Сообщений: 4782



Просмотр профиля
« Ответ #42 : 28 Февраля 2018, 22:47:41 »

Возможно ты прав, надо глянуть учел ли я это в предыдущих версиях процедур. А насчет обнуления ip в mac_uid. Тут смысл не в том, чтоб он был освобожден четко во время, а смысл в том, чтобы всегда хватало свободных ip перед тем как ip запросит подключившийся
Записан
elite
Начальник планеты
NoDeny
Спец
*

Карма: 52
Offline Offline

Сообщений: 1227

In LAN we trust!

358714596
Просмотр профиля
« Ответ #43 : 28 Февраля 2018, 23:52:13 »

Кажется я понял в чем проблема.

Судя по логике биллинга, при выдаче ip, get_ip_by_tag и не только ориентируется на занятость ip по uid=0, если равно 0 то Ip свободен и это работало и работает с pppoe и другими тоннелями когда ip выдается исключительно клиенту в базе.

И тут приходит dhcp через radius. Создавая логику авторизации клиента по dhcp мы понимаем что теперь нужно всем отвечать ACCEPT и выдавать ip с пула, чтобы в дальнейшем клиент мог авторизовать свое подключение и привязаться к учетной записи самостоятельно. И тут всплывает один нюанс.

если клиента нет в бд, отвечает accept, но вместо framed ip выдавай framed pool, чтобы accel выдавал сам гостевой ип из своего пула
Записан
Efendy
Администратор
Спец
*****

Карма: 138
Offline Offline

Сообщений: 4782



Просмотр профиля
« Ответ #44 : 01 Марта 2018, 10:06:01 »

Не. Тогда нужен будет реконнект после того как абон зарегается. Я думаю, можно будет подправить процедуры, чтобы у выданного гостю ip в пуле устанавливалось поле release. Сегодня потестирую и напишу.
Записан
Страниц: 1 2 [3] 4
  Печать  
 
Перейти в:  

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