Pppoe: відмінності між версіями
Sv (обговорення | внесок) Немає опису редагування |
Sv (обговорення | внесок) Немає опису редагування |
||
(Не показано 10 проміжних версій цього користувача) | |||
Рядок 1: | Рядок 1: | ||
<h2> | <h2>PPPoE на Mikrotik</h2> | ||
Возможна работа как со статическими (когда ip прописан явно в учетке абонента и никогда не меняется), так и с динамическими ip. Во втором случае в админке NoDeny создадим пул ip адресов в количестве раз в 5-10 большим чем предполагаемое количество абонентов. Тип ip - "динамический". | |||
[[Файл:Mikrotik_radius.gif]] | [[Файл:Mikrotik_radius.gif]] | ||
Рядок 62: | Рядок 62: | ||
</pre> | </pre> | ||
===Mysql процедуры=== | ===Mysql процедуры=== | ||
Рядок 85: | Рядок 73: | ||
CREATE PROCEDURE `radcheck` (IN login VARCHAR(64)) | CREATE PROCEDURE `radcheck` (IN login VARCHAR(64)) | ||
BEGIN | BEGIN | ||
SELECT | SELECT id,name,'Password' AS Attribute,AES_DECRYPT(passwd,'hardpass') AS Value,'==' | ||
FROM users WHERE name=login; | |||
END$$ | END$$ | ||
DELIMITER ; | DELIMITER ; | ||
Рядок 95: | Рядок 84: | ||
CREATE PROCEDURE `radreply`(IN login VARCHAR(64)) | CREATE PROCEDURE `radreply`(IN login VARCHAR(64)) | ||
BEGIN | 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; | |||
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$$ | END$$ | ||
DELIMITER ; | DELIMITER ; | ||
Рядок 126: | Рядок 100: | ||
DROP PROCEDURE IF EXISTS `radupdate`; | DROP PROCEDURE IF EXISTS `radupdate`; | ||
DELIMITER $$ | DELIMITER $$ | ||
CREATE PROCEDURE `radupdate`( | CREATE PROCEDURE `radupdate`(IN login VARCHAR(64), IN ip VARCHAR(16), IN properties VARCHAR(255)) | ||
BEGIN | 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,':',''))); | |||
END$$ | |||
DELIMITER ; | |||
</pre> | |||
<pre> | |||
DROP PROCEDURE IF EXISTS `radstop`; | |||
DELIMITER $$ | |||
CREATE PROCEDURE `radstop`(IN login VARCHAR(64)) | |||
BEGIN | |||
DECLARE usr_id INT; | |||
SELECT id INTO usr_id FROM users WHERE name=login LIMIT 1; | |||
DELETE FROM auth_now WHERE ip = get_ip(usr_id) LIMIT 1; | |||
END$$ | END$$ | ||
DELIMITER ; | DELIMITER ; | ||
Рядок 140: | Рядок 126: | ||
<pre> | <pre> | ||
CALL radreply(' | CALL radreply('test'); | ||
</pre> | </pre> | ||
Где test - это логин существующего абонента. В ответе должны получить ip, который привязан к абоненту, либо, если ни один ip не привязан - будет выдан свободный из пула ip биллинга. Если получаем ошибку: | |||
* ''ERROR 1267 (HY000): Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8_unicode_ci,IMPLICIT) for operation '=''' - выполним: | * ''ERROR 1267 (HY000): Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8_unicode_ci,IMPLICIT) for operation '=''' - выполним: | ||
<pre> | <pre> | ||
Рядок 162: | Рядок 146: | ||
<source lang='bash'> | <source lang='bash'> | ||
radtest | radtest login pass 127.0.0.1 0 hardpass5 | ||
</source> | </source> | ||
Если получаем ошибку ''radclient:: Failed to find IP address for имя_нашего_сервера'' - в /etc/hosts не прописано имя нашего сервера. | где login и test соответственно логин и пароль реально существующей клиентской записи в NoDeny. Если получаем ошибку ''radclient:: Failed to find IP address for имя_нашего_сервера'' - в /etc/hosts не прописано имя нашего сервера. | ||
Должны получить примерно такой ответ: | Должны получить примерно такой ответ: | ||
<pre> | <pre> | ||
rad_recv: Access- | rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=138, length=38 | ||
Framed-IP-Address = 10.0. | Framed-IP-Address = 10.0.0.10 | ||
Framed-IP-Netmask = 255.255.255.255 | |||
Framed-Protocol = PPP | |||
</pre> | </pre> | ||
Рядок 191: | Рядок 175: | ||
Добавляем: | Добавляем: | ||
<pre> | <pre> | ||
client | client 1.1.1.1 { | ||
secret = hardpass5 | secret = hardpass5 | ||
shortname = Mikrotik | shortname = Mikrotik | ||
Рядок 198: | Рядок 182: | ||
</pre> | </pre> | ||
Здесь 1.1.1.1 - ip Микротика (тот ip, который смотрит на сервер NoDeny - смотрите схему выше) | |||
<pre> | <pre> | ||
Рядок 206: | Рядок 191: | ||
interface pppoe-server server add interface=ether1 service-name=pppoe-in authentication=chap | interface pppoe-server server add interface=ether1 service-name=pppoe-in authentication=chap | ||
ip firewall nat add chain=srcnat action=src-nat to-addresses=2.2.2.2 | ip firewall nat add chain=srcnat action=src-nat to-addresses=2.2.2.2 | ||
</pre> | |||
==PPPoE с привязкой к мак== | |||
<source lang='bash'> | |||
ee /usr/local/etc/raddb/sql.conf | |||
</source> | |||
В конце файла находим строку ''authorize_check_query = ...'' и меняем ее на: | |||
<pre> | |||
authorize_check_query = "call radcheck('%{User-Name}', '%{Calling-Station-Id}')" | |||
</pre> | |||
Здесь мы добавили в процедуру radcheck параметр ''Calling-Station-Id'' - в этом параметре mikrotik передает мак абонента. Когда клиент пытается сконнектиться, radius запускает процедуру radcheck и передает ей логин и мак. В случае если логин существует в базе данных и к нему подвязан точно такой же мак - процедура должна вернуть radius-у пароль абонента. Радиус сверяет пароль полученный от клиента с его реальным и при совпадении создает pppoe-сессию. В случае, если мак иной - процедура ничего не должна возвращать, в этом случае radius будет считать, что такого логина не существует. | |||
В mysql меняем процедуру radcheck: | |||
<pre> | |||
DROP PROCEDURE IF EXISTS `radcheck`; | |||
DELIMITER $$ | |||
CREATE PROCEDURE `radcheck` (IN login VARCHAR(64), IN usr_mac VARCHAR(64)) | |||
BEGIN | |||
DECLARE usr_id INT; | |||
DECLARE usr_pass VARCHAR(64) DEFAULT NULL; | |||
SELECT LOWER(REPLACE(usr_mac, ':', '')) INTO usr_mac; | |||
SELECT id, AES_DECRYPT(passwd,'hardpass') INTO usr_id, usr_pass | |||
FROM users WHERE name=login; | |||
IF usr_id IS NOT NULL AND | |||
(SELECT 1 FROM mac_uid WHERE uid=usr_id AND mac=usr_mac) | |||
THEN | |||
SELECT usr_id, login, 'Password' AS Attribute, usr_pass AS Value, '=='; | |||
END IF; | |||
END$$ | |||
DELIMITER ; | |||
</pre> | |||
Проверим работоспособность: | |||
<pre> | |||
call radcheck('11', '00:11:22:33:44:55'); | |||
</pre> | |||
Должны получить: | |||
<pre> | |||
+--------+-------+-----------+------------+----+ | |||
| usr_id | login | Attribute | Value | == | | |||
+--------+-------+-----------+------------+----+ | |||
| 1 | 11 | Password | 2234157631 | == | | |||
+--------+-------+-----------+------------+----+ | |||
</pre> | |||
Здесь: 11 - логин абонента, 00:11:22:33:44:55 - мак адрес, 2234157631 - пароль | |||
Проверим ситуацию, когда абонент сменил мак адрес | |||
<pre> | |||
call radcheck('11', '00:11:11:11:11:11'); | |||
</pre> | |||
В ответ должны получить 0 строк. | |||
Запускаем radius с выводом данных на консоль: | |||
<source lang='bash'> | |||
/usr/local/etc/rc.d/radiusd stop | |||
radiusd -X | |||
</source> | |||
Пытаемся подсоединиться по pppoe и в консоли должны увидеть следующее: | |||
<pre> | |||
... | |||
... | |||
[sql] expand: call radcheck('%{User-Name}', '%{Calling-Station-Id}') -> call radcheck('11', '00:11:22:33:44:55') | |||
... | |||
</pre> | </pre> |
Поточна версія на 09:02, 21 квітня 2017
PPPoE на Mikrotik
Возможна работа как со статическими (когда ip прописан явно в учетке абонента и никогда не меняется), так и с динамическими ip. Во втором случае в админке NoDeny создадим пул ip адресов в количестве раз в 5-10 большим чем предполагаемое количество абонентов. Тип ip - "динамический".
Установка Radius
Поскольку понадобится radius с модулем mysql, установим его не из бинарных пакетов (pkg install freeradius), а из портов:
cd /usr/ports/net/freeradius2 && make install clean
Обязательно поставим галку напротив опции MYSQL
rm /usr/local/etc/raddb/sites-enabled/default
ee /usr/local/etc/raddb/sites-enabled/nodeny
Вставляем следующий текст:
authorize { sql } authenticate { Auth-Type PAP { pap } } preacct { acct_unique preprocess } accounting { detail sql exec } session { radutmp sql } post-auth { sql }
cp /usr/local/nodeny/etc/raddb/* /usr/local/etc/raddb/
echo radiusd_enable=YES >> /etc/rc.conf
ee /usr/local/etc/raddb/radiusd.conf
Раскомментируем строку (найти проще всего так: ctrl+y, затем текст "sql.conf", затем enter):
$INCLUDE sql.conf
Mysql процедуры
ALTER DATABASE nodeny CHARACTER SET utf8 COLLATE utf8_general_ci;
DROP PROCEDURE IF EXISTS `radcheck`; DELIMITER $$ CREATE PROCEDURE `radcheck` (IN login VARCHAR(64)) BEGIN SELECT id,name,'Password' AS Attribute,AES_DECRYPT(passwd,'hardpass') AS Value,'==' FROM users WHERE name=login; END$$ DELIMITER ;
DROP PROCEDURE IF EXISTS `radreply`; DELIMITER $$ CREATE PROCEDURE `radreply`(IN login 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(usr_id) 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 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,':',''))); END$$ DELIMITER ;
DROP PROCEDURE IF EXISTS `radstop`; DELIMITER $$ CREATE PROCEDURE `radstop`(IN login VARCHAR(64)) BEGIN DECLARE usr_id INT; SELECT id INTO usr_id FROM users WHERE name=login LIMIT 1; DELETE FROM auth_now WHERE ip = get_ip(usr_id) LIMIT 1; END$$ DELIMITER ;
Проверим:
CALL radreply('test');
Где test - это логин существующего абонента. В ответе должны получить ip, который привязан к абоненту, либо, если ни один ip не привязан - будет выдан свободный из пула ip биллинга. Если получаем ошибку:
- ERROR 1267 (HY000): Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8_unicode_ci,IMPLICIT) for operation '=' - выполним:
ALTER DATABASE nodeny CHARACTER SET utf8 COLLATE utf8_general_ci;
и пересоздаем процедуры
Запускам Radius
/usr/local/etc/rc.d/radiusd start
Проверяем:
radtest login pass 127.0.0.1 0 hardpass5
где login и test соответственно логин и пароль реально существующей клиентской записи в NoDeny. Если получаем ошибку radclient:: Failed to find IP address for имя_нашего_сервера - в /etc/hosts не прописано имя нашего сервера.
Должны получить примерно такой ответ:
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=138, length=38 Framed-IP-Address = 10.0.0.10 Framed-IP-Netmask = 255.255.255.255 Framed-Protocol = PPP
В ином случае тушим radius и запускаем в режиме детального вывода:
/usr/local/etc/rc.d/radiusd stop
radiusd -X
Продолжаем настройку. Добавим микротик (10.1.0.11) в настройки радиуса:
ee /usr/local/etc/raddb/clients.conf
Добавляем:
client 1.1.1.1 { secret = hardpass5 shortname = Mikrotik nastype = cisco }
Здесь 1.1.1.1 - ip Микротика (тот ip, который смотрит на сервер NoDeny - смотрите схему выше)
radius add address=1.1.1.2 secret=hardpass5 service=ppp radius incoming set accept=yes ppp aaa set accounting=yes use-radius=yes interim-update=50 ppp profile set default local-address=2.2.2.2 dns-server=2.2.2.2 interface pppoe-server server add interface=ether1 service-name=pppoe-in authentication=chap ip firewall nat add chain=srcnat action=src-nat to-addresses=2.2.2.2
PPPoE с привязкой к мак
ee /usr/local/etc/raddb/sql.conf
В конце файла находим строку authorize_check_query = ... и меняем ее на:
authorize_check_query = "call radcheck('%{User-Name}', '%{Calling-Station-Id}')"
Здесь мы добавили в процедуру radcheck параметр Calling-Station-Id - в этом параметре mikrotik передает мак абонента. Когда клиент пытается сконнектиться, radius запускает процедуру radcheck и передает ей логин и мак. В случае если логин существует в базе данных и к нему подвязан точно такой же мак - процедура должна вернуть radius-у пароль абонента. Радиус сверяет пароль полученный от клиента с его реальным и при совпадении создает pppoe-сессию. В случае, если мак иной - процедура ничего не должна возвращать, в этом случае radius будет считать, что такого логина не существует.
В mysql меняем процедуру radcheck:
DROP PROCEDURE IF EXISTS `radcheck`; DELIMITER $$ CREATE PROCEDURE `radcheck` (IN login VARCHAR(64), IN usr_mac VARCHAR(64)) BEGIN DECLARE usr_id INT; DECLARE usr_pass VARCHAR(64) DEFAULT NULL; SELECT LOWER(REPLACE(usr_mac, ':', '')) INTO usr_mac; SELECT id, AES_DECRYPT(passwd,'hardpass') INTO usr_id, usr_pass FROM users WHERE name=login; IF usr_id IS NOT NULL AND (SELECT 1 FROM mac_uid WHERE uid=usr_id AND mac=usr_mac) THEN SELECT usr_id, login, 'Password' AS Attribute, usr_pass AS Value, '=='; END IF; END$$ DELIMITER ;
Проверим работоспособность:
call radcheck('11', '00:11:22:33:44:55');
Должны получить:
+--------+-------+-----------+------------+----+ | usr_id | login | Attribute | Value | == | +--------+-------+-----------+------------+----+ | 1 | 11 | Password | 2234157631 | == | +--------+-------+-----------+------------+----+
Здесь: 11 - логин абонента, 00:11:22:33:44:55 - мак адрес, 2234157631 - пароль
Проверим ситуацию, когда абонент сменил мак адрес
call radcheck('11', '00:11:11:11:11:11');
В ответ должны получить 0 строк.
Запускаем radius с выводом данных на консоль:
/usr/local/etc/rc.d/radiusd stop
radiusd -X
Пытаемся подсоединиться по pppoe и в консоли должны увидеть следующее:
... ... [sql] expand: call radcheck('%{User-Name}', '%{Calling-Station-Id}') -> call radcheck('11', '00:11:22:33:44:55') ...