Efendy
|
|
« : 14 Октября 2013, 14:04:03 » |
|
Внимание. Актуальная версия: http://forum.nodeny.com.ua/index.php?topic=2919.0Недавно я добавил теги в пул ip. Наверное мало кто понимает зачем это нужно. Тег - это метка, которая может быть у ip адреса. Сделана для того, чтобы мы в разных ситуациях могли присваивать клиенту разные ip в зависимости от метки. Например, у нас есть несколько NAS, стоящих в разных районах. Клиенты подключаются по PPPoE и получают ip динамически. Мы хотим, чтобы в зависимости от района выдавался ip из определенной подсетки. Если бы ип был статический, то можно было написать в параметрах группы, что для этой группы выдавать ip из такого-то диапазона. Но в случае динамических ip, их выдает mysql процедура, которая не умеет выполнять такие операции (по крайней мере я боюсь писать такую громадную процедуру). Поэтому мы поступим иначе. Мы создадим процедуру выдачи ip в зависимости от тега: DROP FUNCTION IF EXISTS `get_ip_by_tag`; DELIMITER $$ CREATE FUNCTION `get_ip_by_tag` ( user_id INTEGER UNSIGNED, tag VARCHAR(64) ) RETURNS VARCHAR(15) NO SQL BEGIN DECLARE user_ip VARCHAR(15); DECLARE real_ip VARCHAR(15);
SELECT 1 INTO real_ip FROM users_services WHERE uid = user_id AND tags LIKE '%,realip,%'; UPDATE ip_pool SET uid = user_id, `release` = UNIX_TIMESTAMP() + 300 WHERE (uid = 0 OR uid = user_id) AND type = 'dynamic' AND realip = IF(real_ip>0,1,0) AND tags LIKE CONCAT('%,', tag, ',%') ORDER BY uid DESC, id ASC LIMIT 1;
SELECT INET_NTOA(ip) INTO user_ip FROM ip_pool WHERE uid = user_id LIMIT 1; RETURN user_ip; END$$ DELIMITER ; В админке, в настройке пула ip, выберем какие-нибудь ip из середины диапазона или создадим новый и присвоим им тег, скажем, '10.0.0.1' (без кавычек). Также выберем другой диапазон и установим тег в '10.1.0.1'. Проверяем, что get_ip_by_tag работает: SELECT get_ip_by_tag(1,'10.1.0.1')
Здесь 1 - id существующего клиента, у которого не должно быть ни одного статического ip. В mysql меняем процедуры для радиуса: DROP PROCEDURE IF EXISTS `radreply`; DELIMITER $$ CREATE PROCEDURE `radreply`(IN login VARCHAR(64), 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 ;
DROP PROCEDURE IF EXISTS `radupdate`; DELIMITER $$ CREATE PROCEDURE `radupdate`(IN login VARCHAR(64), IN ip VARCHAR(16), IN properties VARCHAR(255), 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; CALL set_auth(usr_ip, CONCAT('mod=pppoe;',REPLACE(properties,':',''))); END$$ DELIMITER ;
Меняем sql.conf радиуса: authorize_reply_query = "call radreply('%{User-Name}', '%{NAS-IP-Address}')" postauth_query = "call radupdate('%{User-Name}','%{Framed-IP-Address}',\ 'user=%{Calling-Station-Id};nas=%{NAS-IP-Address}', '%{NAS-IP-Address}')" accounting_update_query = "call radupdate('%{User-Name}','%{Framed-IP-Address}',\ 'user=%{Calling-Station-Id};nas=%{NAS-IP-Address}', '%{NAS-IP-Address}')"
Теперь в зависимости от ip NAS, будет выдаваться ip либо из одного, либо с другого диапазона (в зависимости от того, в котором будет тег 10.0.0.1 или 10.1.0.1). Лучше, конечно, чтобы теги были не ip сервера, а, например, NAS1 или NAS2. Но тогда нужно модифицировать конфиг радиуса, чтобы он конвертил ip NAS в уловное имя NAS1 (NAS2...). Скорее всего, в параметрах к радиусу передается не тока ип NAS, но и его имя или какой-нить еще нужный параметр, тогда можно было его указать в теге. Сейчас я не имею возможности это проверить. Поэтому кому не лень - отпишитесь
|
|
« Последнее редактирование: 28 Февраля 2017, 09:01:17 от Efendy »
|
Записан
|
|
|
|
Groov
NoDeny
Постоялец
Карма: -3
Offline
Сообщений: 100
|
|
« Ответ #1 : 14 Октября 2013, 16:51:56 » |
|
А если надо что бы на всех NAS серверах эта под сеть ?
|
|
|
Записан
|
|
|
|
VitalVas
NoDeny
Спец
Карма: 60
Offline
Сообщений: 991
|
|
« Ответ #2 : 16 Октября 2013, 19:24:20 » |
|
А если надо что бы на всех NAS серверах эта под сеть ?
Поставить вместо "%{NAS-IP-Address}" свой общий тег
|
|
|
Записан
|
|
|
|
SeMant
NoDeny
Старожил
Карма: 4
Offline
Сообщений: 266
|
|
« Ответ #3 : 28 Июля 2014, 07:23:51 » |
|
Здравствуйте! Хочу всё уточнить, так чтобы точно всё получилось. Добавляю функцию get_ip_by_tag Меняю процедуру radreply (по примеру выше) и radupdate. Кстати как должна выглядеть radupdate, а то Я тут не совсем ... ? DROP PROCEDURE IF EXISTS `radupdate`; DELIMITER $$ CREATE PROCEDURE `radupdate`(IN login VARCHAR(64), IN ip VARCHAR(16), IN properties VARCHAR(255), 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; CALL set_auth(usr_ip, CONCAT('mod=pppoe;',REPLACE(properties,':',''))); END$$ DELIMITER ; В sql.conf вместо authorize_reply_query = "call radreply('%{User-Name}')" ставлю authorize_reply_query = "call radreply('%{User-Name}', '%{NAS-IP-Address}')" Добавляю пулы ип адресов, а в тегах указываю ипы Насов, как в clients.conf. Нужно ли ещё что-то и правильная ли у меня процедура radupdate ?
|
|
|
Записан
|
|
|
|
Efendy
|
|
« Ответ #4 : 28 Июля 2014, 11:46:17 » |
|
Изменил первое сообщение - добавил недостающее
|
|
|
Записан
|
|
|
|
SeMant
NoDeny
Старожил
Карма: 4
Offline
Сообщений: 266
|
|
« Ответ #5 : 28 Июля 2014, 12:24:01 » |
|
Всё сделал. SELECT get_ip_by_tag(1,'10.1.0.1') Ипы из пула выдаёт правильно. В админке не показывает авторизованых и пропадает инет. Что не так ?
|
|
|
Записан
|
|
|
|
Efendy
|
|
« Ответ #6 : 28 Июля 2014, 13:00:45 » |
|
что выдает CALL radreply('логин клиента', 'ip сервера'); не возвращает ли ошибку: CALL radupdate('логин клиента', 'ip клиента', '', 'ip сервера'); если запустить radiusd -X выдает ошибки?
|
|
|
Записан
|
|
|
|
SeMant
NoDeny
Старожил
Карма: 4
Offline
Сообщений: 266
|
|
« Ответ #7 : 28 Июля 2014, 22:27:44 » |
|
что выдает CALL radreply('логин клиента', 'ip сервера'); не возвращает ли ошибку: CALL radupdate('логин клиента', 'ip клиента', '', 'ip сервера'); если запустить radiusd -X выдает ошибки? Я тупанул в sql.conf. Все авторизовываются, сесии не рвутся. Вот только авторизованым ипы по Насам не выдаёт, всё по порядку или 127.0.0.2. Функцию get_ip_by_tag взял, как ты говорил, с forum.nodeny.com.ua/index.php?topic=2491.msg25814#msg25814. К стати пробовал функцию с этой темы, почему-то всем у кого статический реальный ип вешает ещё и динамический вторым. На radiusd -X выдаёт из ошибок только Failed binding to authentication address * port 1812: Address already in use /usr/local/etc/raddb/radiusd.conf[240]: Error binding to port for 0.0.0.0 port 1812
|
|
|
Записан
|
|
|
|
0xbad0c0d3
гуру nodeny )
NoDeny
Спец
Карма: 116
Offline
Сообщений: 1059
|
|
« Ответ #8 : 28 Июля 2014, 23:06:18 » |
|
Ну наверно нужно стопнуть уже запущеный радиус... А вообще, откройте для себя radmin, radsniff - полезно для дебага в боевых условиях, только нужно в radiusd.conf добавить или разрешить инклюд sites-available/control-socket listen { type = control socket = "/var/run/radiusd/radiusd.sock" mode = rw }
|
|
|
Записан
|
|
|
|
fet4
|
|
« Ответ #9 : 06 Декабря 2016, 23:33:17 » |
|
Ребят может кто изменял процедуры radreply и radupdate под dhcp поделитесь пожалуйста. На сколько я понял меняется в них SELECT get_ip(usr_id) INTO usr_ip;
на SELECT get_ip_by_tag(usr_id, tag) INTO usr_ip;
И добавляется переменная tag VARCHAR(64). Пытаюсь отредактировать процедуры с h__p://nodeny.com.ua:8080/wiki/index.php/Dhcp%2BRadius но что-то не получается, хотя функция get_ip_by_tag работает. Подскажите что еще нужно менять.
|
|
|
Записан
|
|
|
|
Pa4ka
|
|
« Ответ #10 : 07 Декабря 2016, 09:14:59 » |
|
Ребят может кто изменял процедуры radreply и radupdate под dhcp поделитесь пожалуйста. На сколько я понял меняется в них SELECT get_ip(usr_id) INTO usr_ip;
на SELECT get_ip_by_tag(usr_id, tag) INTO usr_ip;
И добавляется переменная tag VARCHAR(64). Пытаюсь отредактировать процедуры с h__p://nodeny.com.ua:8080/wiki/index.php/Dhcp%2BRadius но что-то не получается, хотя функция get_ip_by_tag работает. Подскажите что еще нужно менять. покажите функцию SHOW CREATE FUNCTION get_ip_by_tag;
|
|
|
Записан
|
|
|
|
fet4
|
|
« Ответ #11 : 07 Декабря 2016, 10:24:06 » |
|
вот такое показывает, она такая же как в первом посте, в ней ничего не менял mysql> SHOW CREATE FUNCTION get_ip_by_tag; +---------------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | Function | sql_mode | Create Function | character_set_client | collation_connection | Database Collation | +---------------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | get_ip_by_tag | | 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);
SELECT 1 INTO real_ip FROM users_services WHERE uid = user_id AND tags LIKE '%,realip,%'; UPDATE ip_pool SET uid = user_id, `release` = UNIX_TIMESTAMP() + 300 WHERE (uid = 0 OR uid = user_id) AND type = 'dynamic' AND realip = IF(real_ip>0,1,0) AND tags LIKE CONCAT('%,', tag, ',%') ORDER BY uid DESC, id ASC LIMIT 1;
SELECT INET_NTOA(ip) INTO user_ip FROM ip_pool WHERE uid = user_id LIMIT 1; RETURN user_ip; END | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | +---------------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ 1 row in set (0.00 sec)
Мне кажется проблема в radreply от dhcp т.к. там прям в этой процедуре происходит выборка из пула.
|
|
|
Записан
|
|
|
|
Pa4ka
|
|
« Ответ #12 : 07 Декабря 2016, 10:49:01 » |
|
вот такое показывает, она такая же как в первом посте, в ней ничего не менял mysql> SHOW CREATE FUNCTION get_ip_by_tag; +---------------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | Function | sql_mode | Create Function | character_set_client | collation_connection | Database Collation | +---------------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | get_ip_by_tag | | 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);
SELECT 1 INTO real_ip FROM users_services WHERE uid = user_id AND tags LIKE '%,realip,%'; UPDATE ip_pool SET uid = user_id, `release` = UNIX_TIMESTAMP() + 300 WHERE (uid = 0 OR uid = user_id) AND type = 'dynamic' AND realip = IF(real_ip>0,1,0) AND tags LIKE CONCAT('%,', tag, ',%') ORDER BY uid DESC, id ASC LIMIT 1;
SELECT INET_NTOA(ip) INTO user_ip FROM ip_pool WHERE uid = user_id LIMIT 1; RETURN user_ip; END | utf8mb4 | utf8mb4_general_ci | utf8_general_ci | +---------------+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ 1 row in set (0.00 sec)
Мне кажется проблема в radreply от dhcp т.к. там прям в этой процедуре происходит выборка из пула. Эта функция точно выдает IP только с того пула с тем тегом который Вы указывает? Я просто не могу понять что именно у Вас не получаеться.
|
|
|
Записан
|
|
|
|
fet4
|
|
« Ответ #13 : 07 Декабря 2016, 11:06:10 » |
|
SELECT get_ip_by_tag(1,'10.1.0.1') выполняю все ок, берется с нужного пула. А вот radreply | radreply_dhcp | | CREATE DEFINER=`nodeny`@`%` PROCEDURE `radreply_dhcp`(IN login VARCHAR(64), tag VARCHAR(64)) BEGIN DECLARE usr_mac VARCHAR(12); DECLARE usr_ip VARCHAR(15); DECLARE usr_id INT; DECLARE add_attr MEDIUMTEXT; DECLARE line MEDIUMTEXT; DECLARE i INT DEFAULT 1; SELECT REPLACE(login, ':', '') INTO usr_mac; SELECT uid INTO usr_id FROM mac_uid WHERE mac=usr_mac; 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; ELSE START TRANSACTION; SELECT INET_NTOA(ip) INTO usr_ip FROM ip_pool p WHERE uid=0 AND type='dynamic' 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, usr_mac, INET_ATON(usr_ip), 0, UNIX_TIMESTAMP(), 0, 0, 0) ON DUPLICATE KEY UPDATE ip=INET_ATON(usr_ip), time=UNIX_TIMESTAMP(); COMMIT; SELECT INET_NTOA(ip) INTO usr_ip FROM mac_uid WHERE mac=usr_mac; END IF; SELECT NULL, login, 'Framed-IP-Address', usr_ip, '=';
SELECT radius_attr INTO add_attr FROM users_services WHERE uid=usr_id AND tags LIKE '%,inet,%' LIMIT 1;
attr_loop: WHILE TRUE DO SELECT strSplit(add_attr, '\n', i) INTO line; IF LENGTH(line) = 0 OR i > 20 THEN LEAVE attr_loop; END IF; IF line LIKE '%+=%' THEN SELECT NULL,login,strSplit(line, '+=', 1),strSplit(line, '+=', 2),'+='; ELSEIF line LIKE '%=%' THEN SELECT NULL,login,strSplit(line, '=', 1),strSplit(line, '=', 2),'='; END IF; SET i = i + 1; END WHILE; END
выполняю CALL radreply_dhcp('74:e5:43:8f:c1:17', '172.20.0.2')
и проскакивают с других пулов.
|
|
|
Записан
|
|
|
|
Efendy
|
|
« Ответ #14 : 07 Декабря 2016, 11:42:35 » |
|
В пппое когда создается соединение, то у нас всегда есть id пользователя, которое мы получаем по логину. Если у тебя радиус для дхцп настроен так, чтобы выдавать ip для неизвестных мак, то естественно одно get_ip_by_tag не пожет - там первым параметром идет id абонента. Т.е. если в твоем случае '74:e5:43:8f:c1:17' не внесен в таблицу mac_uid, то в процедуре radreply_dhcp сработает ветка START TRANSACTION блаблабла COMMIT, где тег не принимается во внимание. Думаю, что нужно заменить SELECT INET_NTOA(ip) INTO usr_ip FROM ip_pool p WHERE uid=0 AND type='dynamic' AND NOT EXISTS (SELECT ip FROM mac_uid WHERE ip=p.ip) ORDER BY RAND() LIMIT 1 FOR UPDATE; на 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; типа такого
|
|
|
Записан
|
|
|
|
|