Привязка ip к login

Матеріал з NoDeny
Версія від 10:06, 17 жовтня 2018, створена Sv (обговорення | внесок)
(різн.) ← Попередня версія | Поточна версія (різн.) | Новіша версія → (різн.)
Перейти до навігації Перейти до пошуку

Если к учетной записи подключено несколько ip адресов и есть необходимость выдавать ip в зависимости от логина - этот модуль для вас. В админке напротив ip адреса появится выпадающий список, где можно выбрать число, связанное с данным ip.

Это число будет являться частью логина. Например, у абонента существует учетная запись ivanov и подключены 3 ip и для каждого ip выбрано число (как в видео выше):

10.0.0.205 - 1
10.0.0.206 - 3
10.0.0.207 - 4

Чтобы при авторизации по pppoe ему был выдан адрес 10.0.0.206 необходимо в качестве логина использовать ivanov+3, для 10.0.0.207 - ivanov+4

Чтобы эта схема заработала, необходимо создать mysql-процедуру, которая будет выдавать ip в зависимости от числа в фрагменте логина:

DROP FUNCTION IF EXISTS `get_ip_by_num`;
DELIMITER $$
CREATE FUNCTION `get_ip_by_num` ( user_id INTEGER UNSIGNED, num INTEGER )
    RETURNS VARCHAR(15) NO SQL
BEGIN
    DECLARE user_ip VARCHAR(15);
    DECLARE real_ip VARCHAR(15);

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

    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,%';
    UPDATE ip_pool SET uid = user_id, `release` = UNIX_TIMESTAMP() + 300
        WHERE id = (SELECT id FROM (
            (
              SELECT id, uid FROM ip_pool 
              WHERE uid = 0 AND type = 'dynamic' AND realip = IF(real_ip>0,1,0)
              LIMIT 1
            ) UNION (
              SELECT id, uid FROM ip_pool
              WHERE uid = user_id AND type = 'dynamic' AND realip = IF(real_ip>0,1,0)
              LIMIT 1
            )
        ) AS tbl ORDER BY uid DESC LIMIT 1);

    SELECT INET_NTOA(ip) INTO user_ip FROM ip_pool
        WHERE uid = user_id LIMIT 1;
    RETURN user_ip;
END$$
DELIMITER ; 

Проверим ее работоспособность:

SELECT get_ip_by_num(357, 3);

При условии, что id абонента ivanov = 357, должно выдать:

+-----------------------+
| get_ip_by_num(357, 3) |
+-----------------------+
| 10.0.0.206            |
+-----------------------+

Так же необходимо изменить radius-процедуры:

DROP PROCEDURE IF EXISTS `radcheck`;
DELIMITER $$
CREATE PROCEDURE `radcheck` (IN login VARCHAR(64))
BEGIN
  DECLARE real_login VARCHAR(64) DEFAULT NULL;
  SELECT SUBSTRING_INDEX(login, '+', 1) INTO real_login;
  SELECT id, name, 'Password' AS Attribute, AES_DECRYPT(passwd,'hardpass') AS Value,'=='
    FROM users WHERE name=real_login;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS `radreply`;
DELIMITER $$
CREATE PROCEDURE `radreply`(IN login VARCHAR(64))
BEGIN
  DECLARE usr_id INT;
  DECLARE ip_index INT;
  DECLARE usr_ip VARCHAR(15) DEFAULT NULL;
  DECLARE real_login VARCHAR(64) DEFAULT NULL;

  SELECT SUBSTRING_INDEX(login, '+', 1) INTO real_login;
  SELECT CAST(REPLACE(login, real_login, '') AS UNSIGNED) INTO ip_index;

  SELECT id INTO usr_id FROM users WHERE name=real_login LIMIT 1;
  SELECT get_ip_by_num(usr_id, ip_index) 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))
BEGIN
  DECLARE usr_id INT;
  DECLARE ip_index INT;
  DECLARE usr_ip VARCHAR(15) DEFAULT NULL;
  DECLARE real_login VARCHAR(64) DEFAULT NULL;

  SELECT SUBSTRING_INDEX(login, '+', 1) INTO real_login;
  SELECT CAST(REPLACE(login, real_login, '') AS UNSIGNED) INTO ip_index;

  SELECT id INTO usr_id FROM users WHERE name=real_login LIMIT 1;
  SELECT get_ip_by_num(usr_id, ip_index) INTO usr_ip;
  CALL set_auth(usr_ip, CONCAT('mod=pppoe;',REPLACE(properties,':','')));
END$$
DELIMITER ;

Также необходимо настроить радиус так, чтобы он не экранировал знак плюса в логине, в sql.conf добавьте:

safe-characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.+-_: /"