1001 статья о настройке связки mpd+freeradius3+mysql
===== Ставим порт FreeRadius3 =====
1 2 3 |
cd /usr/ports/net/freeradius3 make config // отмечаем для установки mysql,user,perl install clean |
===== База MySQL =====
Создаем в MySQL базу (например radme), со следующей структурой:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
CREATE TABLE radacct ( radacctid bigint(21) NOT NULL auto_increment, acctsessionid varchar(64) NOT NULL default '', acctuniqueid varchar(32) NOT NULL default '', username varchar(64) NOT NULL default '', groupname 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 NULL default NULL, acctupdatetime datetime NULL default NULL, acctstoptime datetime NULL default NULL, acctinterval int(12) default NULL, acctsessiontime int(12) unsigned default NULL, acctauthentic varchar(32) default NULL, connectinfo_start varchar(50) default NULL, connectinfo_stop varchar(50) default NULL, acctinputoctets bigint(20) default NULL, acctoutputoctets bigint(20) 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 '', PRIMARY KEY (radacctid), UNIQUE KEY acctuniqueid (acctuniqueid), KEY username (username), KEY framedipaddress (framedipaddress), KEY acctsessionid (acctsessionid), KEY acctsessiontime (acctsessiontime), KEY acctstarttime (acctstarttime), KEY acctinterval (acctinterval), KEY acctstoptime (acctstoptime), KEY nasipaddress (nasipaddress) ) ENGINE = INNODB;</code> # # Table structure for table 'radcheck' # CREATE TABLE radcheck ( id int(11) unsigned NOT NULL auto_increment, username varchar(64) NOT NULL default '', attribute varchar(64) 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(64) 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(64) 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(64) 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, username varchar(64) NOT NULL default '', pass varchar(64) NOT NULL default '', reply varchar(32) NOT NULL default '', authdate timestamp NOT NULL, PRIMARY KEY (id) ) ENGINE = INNODB; # # 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, server varchar(64), community varchar(50), description varchar(200) DEFAULT 'RADIUS Client', PRIMARY KEY (id), KEY nasname (nasname) ); ALTER TABLE `radcheck` ADD UNIQUE(`username`); ALTER TABLE `radreply` ADD UNIQUE(`username`); ALTER TABLE `radpostauth` ADD `ip` VARCHAR(20) NOT NULL AFTER `authdate`, ADD `mac` VARCHAR(40) NOT NULL AFTER `ip`, ADD `session_id` VARCHAR(40) NOT NULL AFTER `mac`, ADD `comment` VARCHAR(200) NOT NULL AFTER `session_id; |
===== Модуль mysql на freeradius3 =====
Настроиваем взаимодействие с MySQL
1 |
mcedit /usr/local/etc/raddb/mods-enabled/sql |
вставляем:
sql {
driver = "rlm_sql_mysql"
dialect = "mysql"
server = "localhost"
login = "iergfkle"
password = "eruiofhoe"
radius_db = "radme"
acct_table1 = "radacct"
acct_table2 = "radacct"
postauth_table = "radpostauth"
authcheck_table = "radcheck"
groupcheck_table = "radgroupcheck"
authreply_table = "radreply"
groupreply_table = "radgroupreply"
usergroup_table = "radusergroup"
delete_stale_sessions = yes
logfile = ${logdir}/sqllog.sql
pool {
start = 5
min = 4
max = ${thread[pool].max_servers}
spare = 3
uses = 0
lifetime = 0
idle_timeout = 60
}
client_table = «nas»
$INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf
}
===== Секция clients.conf =====
Настройки clients.conf для обмена с mpd45
Открываем:
mcedit /usr/local/etc/raddb/clients.conf
Фактически оригинальный конфиг, правим только . Оный используется в mpd.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
client localhost { ipaddr = 127.0.0.1 proto = * secret = oweurfieh require_message_authenticator = no shortname = localhost limit { max_connections = 1600 lifetime = 0 idle_timeout = 30 } } client localhost_ipv6 { ipv6addr = ::1 secret = padlopavel } |
===== Настраиваем «сайт» =====
Добавляем правила обработки sql:
1 |
mcedit /usr/local/etc/raddb/sites-enabled/default |
Фактически можно скопировать данный конфиг:
server default {
listen {
type = auth
ipaddr = *
port = 0
limit {
max_connections = 16
lifetime = 0
idle_timeout = 30
}
}
listen {
ipaddr = *
port = 0
type = acct
limit {
}
}
listen {
type = auth
port = 0
limit {
max_connections = 16
lifetime = 0
idle_timeout = 30
}
}
listen {
ipv6addr = ::
port = 0
type = acct
limit {
}
}
authorize {
filter_username
preprocess
chap
mschap
digest
suffix
eap {
ok = return
}
files
-sql
expiration
logintime
pap
perl #проверяем сколько сессий?
}
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
digest
eap
}
preacct {
preprocess
acct_unique
suffix
files
}
accounting {
detail
unix
-sql
exec
attr_filter.accounting_response
}
session {
}
post-auth {
update {
&reply: += &session-state:
}
-sql
exec
remove_reply_message_if_eap
Post-Auth-Type REJECT {
-sql
attr_filter.access_reject
eap
remove_reply_message_if_eap
}
}
pre-proxy {
}
post-proxy {
eap
}
}
===== Настройка mpd =====
Правим /usr/local/etc/mpd5/mpd.conf, по примеру:
startup:
#configure mpd users
set user admin adminpass
#configure the console
set console self 127.0.0.1 5005
set console open
#configure the web server
# set web self 0.0.0.0 5006
# set web open
set radsrv peer 12.17.12.112 ejrygfue
set radsrv peer 12.17.12.112 kerujf
set radsrv self 12.17.12.112 3799
set radsrv open
default:
load def_conf
def_conf:
create bundle template B
# set iface up-script /usr/local/etc/mpd5/vpn_up_mpd.pl
# set iface down-script /usr/local/etc/mpd5/vpn_down_mpd.pl
set bundle enable compression
set bundle enable encryption
set iface idle 0
set iface disable proxy-arp
set iface mtu 1500
set iface enable tcpmssfix
set ipcp yes vjcomp
set ipcp ranges 16.17.28.1/32 12.18.128.0/21
set ipcp dns 16.17.28.1 16.17.208.2
# set ccp yes mppc
# set mppc yes e40
# set mppc yes e56
# set mppc yes e128
# set mppc yes stateless
set ecp disable dese-bis dese-old
log -echo -ipv6cp -radius -rep
load pptp_server
pptp_server:
set iface enable proxy-arp
set iface idle 1800
set iface enable tcpmssfix
set ipcp yes vjcomp
set bundle enable compression
create link template L pptp
set link action bundle B
set link enable multilink
set link yes acfcomp protocomp
set link no pap chap
set link enable chap
set link keep-alive 10 60
set link mtu 1460
set link enable incoming
set link enable chap chap-msv1 chap-msv2 chap-md5
set pptp self 0.0.0.0
load radius
load common
common:
create link template PPPoE pppoe
set link enable no-orig-auth
set link max-children 1000
set link mtu 1492
set auth max-logins 0
load pppoe
pppoe:
set link action bundle B
set link enable multilink
set link yes acfcomp protocomp
set link disable chap pap eap
set link enable chap chap-msv1 chap-msv2 chap-md5
set link keep-alive 10 60
#pppoe on bge1 with service name «service_name0»
load radius
create link template em0_102 PPPoE
set pppoe iface vlan102
set link enable incoming
radius:
set auth max-logins 10 #разрешаем «много» сессий (чтоб увидеть ошибку в радиуес, иначе до радиуса тупо не доходит инфа, что 2-й абонент пытается подключится.
set auth disable internal
set auth acct-update 10 #абновляем аккаунтинг каждые 10 секунд
set auth enable radius-auth
set auth enable radius-acct
set radius retries 3
set radius timeout 5
set radius server localhost eiurfhie 1812 1813
set radius me localhost
===== Модуль perl =====
Добавляем во freeradius3 модуль perl
mcedit /usr/local/etc/raddb/mods-enabled/perl
perl {
filename = ${modconfdir}/${.:instance}/auth.pl
func_authenticate = authenticate
}
===== Обработчик perl =====
Добавляем обработку проверки «а может есть уже сессия» ?
mcedit /usr/local/etc/raddb/mods-config/perl/auth.pl
#!/usr/local/bin/perl
use strict;
use warnings;
use Data::Dumper;
use DBI;
use Encode;
use POSIX;
our (%RAD_REQUEST, %RAD_REPLY, %RAD_CHECK);
use constant {
};
use constant L_DBG=> 1;
use constant L_AUTH=> 2;
use constant L_INFO=> 3;
use constant L_ERR=> 4;
use constant L_PROXY=> 5;
use constant L_ACCT=> 6;
my $host = «localhost»;
my $port = «3306»;
my $user = «perfioej»;
my $pass = «oeirjfoeri»;
my $db = «radme»;
my $flag=0;
sub authorize {
my $username=$RAD_REQUEST{‘User-Name’};
my $dbh = DBI->connect(«DBI:mysql:$db:$host:$port»,$user,$pass);
#если время обновления последней сессии абонента меньше 5 минут — то авторизоваться не дает — считает что дубль сессии
my $sth = $dbh->prepare(«select count(*) as cnt from radacct where acctupdatetime>date_sub(now(),interval 5 minute) and username=’$username'»);
$sth->execute;
while (my $ref = $sth->fetchrow_arrayref) {$flag=$$ref[0];};
if ($flag eq 1){
$RAD_REPLY{‘Reply-Message’} = «Double sessions!»;
return RLM_MODULE_REJECT;
} else {
$RAD_REPLY{‘Reply-Message’} = «One session! Connecting Ok»;
return RLM_MODULE_OK;
}
}
sub authenticate {
}
sub preacct {
return RLM_MODULE_OK;
}
sub accounting {
&test_call;
return RLM_MODULE_OK;
}
sub checksimul {
return RLM_MODULE_OK;
}
sub pre_proxy {
return RLM_MODULE_OK;
}
sub post_proxy {
return RLM_MODULE_OK;
}
sub post_auth {
return RLM_MODULE_OK;
}
sub xlat {
my ($filename,$a,$b,$c,$d) = @_;
&radiusd::radlog(L_DBG, «From xlat $filename «);
&radiusd::radlog(L_DBG,»From xlat $a $b $c $d «);
local *FH;
open FH, $filename or die «open ‘$filename’ $!»;
local($/) = undef;
my $sub = ;
close FH;
my $eval = qq{ sub handler{ $sub;} };
eval $eval;
eval {main->handler;};
}
sub detach {
&radiusd::radlog(L_DBG,»rlm_perl::Detaching. Reloading. Done.»);
}
sub test_call {
}
sub log_request_attributes {
for (keys %RAD_REQUEST) {
&radiusd::radlog(L_DBG, «RAD_REQUEST: $_ = $RAD_REQUEST{$_}»);
}
}