====== Новый модуль авторизации mikbill.pl для Radius ====== Работает только с версии 3.09.02, на версиях ниже могут быть проблемы так как со стороны ядра биллинга нет контроля соединения * Добавлена проверка соединения с ядром биллинга и его автоматическое восстановление * Добавлено логирование о потери связи \\ Данный код заменить в файле /etc/raddb/mikbill.pl или /etc/freeradius/3.0/mikbill.pl \\ После чего перезапустить радиус. Обратите внимание на $host="127.0.0.1" и $port="22007" если они у вас отличаются! use strict; use vars qw(%RAD_REQUEST %RAD_REPLY %RAD_CHECK); use IO::Socket; use locale; use POSIX; use serialize; setlocale(LC_ALL, 'C'); use constant RLM_MODULE_REJECT=> 0;# /* immediately reject the request */ use constant RLM_MODULE_FAIL=> 1;# /* module failed, don't reply */ use constant RLM_MODULE_OK=> 2;# /* the module is OK, continue */ use constant RLM_MODULE_HANDLED=> 3;# /* the module handled the request, so stop. */ use constant RLM_MODULE_INVALID=> 4;# /* the module considers the request invalid. */ use constant RLM_MODULE_USERLOCK=> 5;# /* reject the request (user is locked out) */ use constant RLM_MODULE_NOTFOUND=> 6;# /* user not found */ use constant RLM_MODULE_NOOP=> 7;# /* module succeeded without doing anything */ use constant RLM_MODULE_UPDATED=> 8;# /* OK (pairs modified) */ use constant RLM_MODULE_NUMCODES=> 9;# /* How many return codes there are */ use constant RADIUS_L_DBG=> 0;# /* debug log */ use constant RADIUS_L_AUTH=> 1;# /* auth log */ use constant RADIUS_L_PROXY=> 2;# /* peroxy log */ use constant RADIUS_L_INFO=> 3;# /* info log */ use constant RADIUS_L_ERROR=> 4;# /* error log */ # mikbill daemon IP address and port my $host="127.0.0.1"; my $port="22007"; # def my $sock; my $answer; my $time=5; sub socket_init { my $sock = new IO::Socket::INET ( PeerAddr => $host, PeerPort => $port, Proto => 'tcp', ) or &radiusd::radlog(RADIUS_L_ERROR, "no connection with mikbill daemon ($host:$port)"); if( length $sock ) { if( $sock->connected() ){ setsockopt($sock, SOL_SOCKET, SO_KEEPALIVE, 1); } } return $sock; } sub StillConnected { return unless defined $sock; return unless $sock->connected(); return 1; } sub check_socket { if (&StillConnected()) { return 1; } elsif(!&StillConnected()){ $sock=&socket_init; } } sub CLONE { $sock=&socket_init; } sub authorize { if(&check_socket()){ print $sock "auth\n"; $answer=<$sock>; print $sock serialize(\%RAD_REQUEST); $answer=<$sock>; print $sock serialize(\%RAD_REPLY); $answer=<$sock>; print $sock serialize(\%RAD_CHECK); $answer=<$sock>; if ($answer eq "reject\n") { return RLM_MODULE_REJECT; } $answer=<$sock>; %RAD_REPLY=%{unserialize($answer)}; $answer=<$sock>; %RAD_CHECK=%{unserialize($answer)}; } else { return RLM_MODULE_REJECT; } return RLM_MODULE_OK; } sub authenticate { if ($RAD_REPLY{'Packet-Type'} eq "Access-Reject") { return RLM_MODULE_REJECT; } else { return RLM_MODULE_OK; } } sub preacct { return RLM_MODULE_OK; } sub accounting { if(&check_socket()){ print $sock "acct\n"; $answer=<$sock>; print $sock serialize(\%RAD_REQUEST); } 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 { if(&check_socket()){ print $sock "post_auth\n"; $answer=<$sock>; print $sock serialize(\%RAD_REQUEST); $answer=<$sock>; print $sock serialize(\%RAD_REPLY); $answer=<$sock>; print $sock serialize(\%RAD_CHECK); $answer=<$sock>; if ($answer eq "reject\n") { return RLM_MODULE_REJECT; } $answer=<$sock>; %RAD_REPLY=%{unserialize($answer)}; $answer=<$sock>; %RAD_CHECK=unserialize($answer); } else { return RLM_MODULE_REJECT; } return RLM_MODULE_OK; } sub xlat { my ($filename,$a,$b,$c,$d) = @_; &radiusd::radlog(1, "From xlat $filename "); &radiusd::radlog(1,"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(0,"rlm_perl::Detaching. Reloading. Done."); } sub test_call { } sub log_request_attributes { for (keys %RAD_REQUEST) { &radiusd::radlog(1, "RAD_REQUEST: $_ = $RAD_REQUEST{$_}"); } }