Включаем python на radius сервере
Поддержка Python необходима для решения задач связанных с биллингом, для этого эту технологию точно используют. 10 лет назад когда люди охотились на мамонтов все использовали perl. Сейчас все больше переписывают на python. freeradius с версии 2.3 есть поддержка языка программирования python. На момент написания статьи текущая версия freeradius 3.0. То есть поддержка есть уже давно. Чтобы не пройти стороной этот вопрос я решил разобраться в этой технологии.
freeradius это не uwsgi
, он не претендует быть универсальным решателем всех проблем с шахматами и библиотекаршами
. Так как это просто сервис AAA (Authentication Authorization Accounting). То что порой от него хочется, так как это решит поставленную задачу, например при авторизации добавить что-то в базу, средствами простых политик осуществить невозможно. И в этом его гениальность, его точная заточка под конкретную задачу. Но проблему решать нужно и в этот момент приходит поддержка python.
[flickr:id=41212453254]
Для начала необходимо подготовить сервер.
Устанавливаем radius
$ sudo apt-get install freeradius
Установилась версия 2.3
# freeradius -v
freeradius: FreeRADIUS Version 2.2.8, for host x86_64-pc-linux-gnu, built on Jul 26 2017 at 15:27:21
Файлы конфигурации находятся в директории /etc/freeradius/
Добавим поддержку python во freeradius. В секцию authorize
допишем python
.
Сконфигурируем модуль
# nano /etc/freeradius/modules/python
python {
mod_authorize = example
func_authorize = authorize
}
На сколько я понял эта конструкция позволяет импортировать from example import authorize
Создадим директорию и файлы, где в python коде мы получим заголовки при авторизации
# mkdir -p /etc/freeradius/modules/python_files/
# nano /etc/freeradius/modules/python_files/example.py
def instantiate(p):
print "*** instantiate ***"
print p
def authorize(p):
print "*** authorize ***"
print p
У меня описано 2 заготовки, хотя используется только authorize, в модуле python можно указать функции на любой AAA случай жизни.
Надо настроить сервис, чтобы freeradius слушал определенный интерфейс и определенный порт, это делается в файле radiud.conf
:
# nano /etc/freeradius/radiusd.conf
В секции listen
ставим ipaddr = *
Подключение python можно проверить командой.
freeradius -X
Это фиаско, братан! Не запускается. Стандартный python должен видеть /etc/freeradius/modules/python_files в противном случае мы увидим:
...
Module: Linked to module rlm_python
Module: Instantiating module "python" from file /etc/freeradius/modules/python
python_init done
python {
mod_authorize = "example"
func_authorize = "authorize"
}
rlm_python:python_load_function: module 'example' is not found
rlm_python:EXCEPT:<type 'exceptions.ImportError'>: No module named example
rlm_python:python_load_function: failed to import python function 'example.authorize'
/etc/freeradius/modules/python[1]: Instantiation failed for module "python"
/etc/freeradius/sites-enabled/default[99]: Failed to find "python" in the "modules" section.
/etc/freeradius/sites-enabled/default[69]: Errors parsing authorize section.
...
Экпортируем путь, перед запуском.
export PYTHONPATH=$PYTHONPATH:/etc/freeradius/modules/python_files/; freeradius -X
Все нормально, сервер запустился
Listening on authentication address * port 1812
Listening on accounting address * port 1813
Listening on authentication address 127.0.0.1 port 18120 as server inner-tunnel
Listening on proxy address * port 1814
Попробуем отправить запрос аутентификации из другой консоли:
radtest --help
radtest [OPTIONS] user passwd radius-server[:port] nas-port-number secret [ppphint] [nasname]
где secret
можно посмотреть в файле /etc/freeradius/clients.conf
radtest testuser 12345 localhost 1812 testing123
В консоли freeradius -X
видим, что нам пришёл стандартный кортеж, следующего содержания:
++[preprocess] = ok
*** authorize ***
(('User-Name', '"testuser"'), ('User-Password', '"12345"'), ('NAS-IP-Address', '127.0.1.1'), ('NAS-Port', '1812'), ('Message-Authenticator', '0x0aa9249e2f437329e7858e82dc210b2e'))
++[python] = ok
Ура! Это победа! Буду рад, если кому-то помог, сократил потраченное время и мучения.
P.S. Скрипт для создания базы данных mysql. Постоянно забываю, где его искать, среди файлов, после установки freeradius.
cat mysql_schema.sql
###########################################################################
# db_mysql.sql rlm_sql - FreeRADIUS SQL Module #
# #
# Database schema for MySQL rlm_sql module #
# #
# To load: #
# mysql -uroot -prootpass radius < db_mysql.sql #
# #
# Mike Machado <mike@innercite.com> #
###########################################################################
#
# Table structure for table 'radacct'
#
CREATE TABLE radacct (
RadAcctId bigint(21) NOT NULL auto_increment,
AcctSessionId varchar(32) NOT NULL default '',
AcctUniqueId varchar(32) NOT NULL default '',
UserName varchar(64) NOT NULL default '',
Realm varchar(64) default '',
NASIPAddress varchar(15) NOT NULL default '',
NASPortId varchar(15) default NULL,
NASPortType varchar(32) default NULL,
AcctStartTime datetime NOT NULL default '0000-00-00 00:00:00',
AcctStopTime datetime NOT NULL default '0000-00-00 00:00:00',
AcctSessionTime int(12) default NULL,
AcctAuthentic varchar(32) default NULL,
ConnectInfo_start varchar(50) default NULL,
ConnectInfo_stop varchar(50) default NULL,
AcctInputOctets bigint(12) default NULL,
AcctOutputOctets bigint(12) default NULL,
CalledStationId varchar(50) NOT NULL default '',
CallingStationId varchar(50) NOT NULL default '',
AcctTerminateCause varchar(32) NOT NULL default '',
ServiceType varchar(32) default NULL,
FramedProtocol varchar(32) default NULL,
FramedIPAddress varchar(15) NOT NULL default '',
AcctStartDelay int(12) default NULL,
AcctStopDelay int(12) default NULL,
PRIMARY KEY (RadAcctId),
KEY UserName (UserName),
KEY FramedIPAddress (FramedIPAddress),
KEY AcctSessionId (AcctSessionId),
KEY AcctUniqueId (AcctUniqueId),
KEY AcctStartTime (AcctStartTime),
KEY AcctStopTime (AcctStopTime),
KEY NASIPAddress (NASIPAddress)
) ;
#
# Table structure for table 'radcheck'
#
CREATE TABLE radcheck (
id int(11) unsigned NOT NULL auto_increment,
UserName varchar(64) NOT NULL default '',
Attribute varchar(32) NOT NULL default '',
op char(2) NOT NULL DEFAULT '==',
Value varchar(253) NOT NULL default '',
PRIMARY KEY (id),
KEY UserName (UserName(32))
) ;
#
# Table structure for table 'radgroupcheck'
#
CREATE TABLE radgroupcheck (
id int(11) unsigned NOT NULL auto_increment,
GroupName varchar(64) NOT NULL default '',
Attribute varchar(32) NOT NULL default '',
op char(2) NOT NULL DEFAULT '==',
Value varchar(253) NOT NULL default '',
PRIMARY KEY (id),
KEY GroupName (GroupName(32))
) ;
#
# Table structure for table 'radgroupreply'
#
CREATE TABLE radgroupreply (
id int(11) unsigned NOT NULL auto_increment,
GroupName varchar(64) NOT NULL default '',
Attribute varchar(32) NOT NULL default '',
op char(2) NOT NULL DEFAULT '=',
Value varchar(253) NOT NULL default '',
PRIMARY KEY (id),
KEY GroupName (GroupName(32))
) ;
#
# Table structure for table 'radreply'
#
CREATE TABLE radreply (
id int(11) unsigned NOT NULL auto_increment,
UserName varchar(64) NOT NULL default '',
Attribute varchar(32) NOT NULL default '',
op char(2) NOT NULL DEFAULT '=',
Value varchar(253) NOT NULL default '',
PRIMARY KEY (id),
KEY UserName (UserName(32))
) ;
#
# Table structure for table 'radusergroup'
#
CREATE TABLE radusergroup (
UserName varchar(64) NOT NULL default '',
GroupName varchar(64) NOT NULL default '',
priority int(11) NOT NULL default '1',
KEY UserName (UserName(32))
) ;
#
# Table structure for table 'radpostauth'
#
CREATE TABLE radpostauth (
id int(11) NOT NULL auto_increment,
user varchar(64) NOT NULL default '',
pass varchar(64) NOT NULL default '',
reply varchar(32) NOT NULL default '',
`date` timestamp NOT NULL,
PRIMARY KEY (id)
) ;
######################################################################
#
# The next table is commented out because it is not
# currently used in the server.
#
#
# Table structure for table 'dictionary'
#
#CREATE TABLE dictionary (
# id int(10) DEFAULT '0' NOT NULL auto_increment,
# Type varchar(30),
# Attribute varchar(64),
# Value varchar(64),
# Format varchar(20),
# Vendor varchar(32),
# PRIMARY KEY (id)
#);
#
# Table structure for table 'nas'
#
CREATE TABLE nas (
id int(10) NOT NULL auto_increment,
nasname varchar(128) NOT NULL,
shortname varchar(32),
type varchar(30) DEFAULT 'other',
ports int(5),
secret varchar(60) DEFAULT 'secret' NOT NULL,
community varchar(50),
description varchar(200) DEFAULT 'RADIUS Client',
PRIMARY KEY (id),
KEY nasname (nasname)
);