Ключевые слова:nas, session, auth, snmp, radius, isp, cisco, acl, freebsd, linux, pptp, vpn, voip, (найти похожие документы)
From: http://www.lanbilling.ru
Date: Mon, 20 May 2006 18:21:07 +0000 (UTC)
Subject: Механизмы прерывания активных сессий на NAS.
Оригинал: http://www.lanbilling.ru/doc/1.8/drop_sessions.html
1. Общее описание
2. Примеры конфигураций:
2.1 Cisco Systems.
2.2 Linux PoPToP.
2.3 FreeBSD mpd.
2.4 Asterisk + VoIP RADIUS.
1. Общее описание
В любой системе, работающей по протоколу RADIUS, учавствуют как
минимум три объекта: пользователь, запрашивающий услугу, сервер
доступа(NAS) ее обеспечивающий и RADIUS сервер (агент в терминах АСР).
Существенным недостатком протокола является его односторонность:
RADIUS сервер может отвечать на запросы NAS'а, но не может выступать
инициатором запроса. Когда пользователь успешно прошел аутентификацию,
RADIUS сервер выдает в ответном пакете максимальную длительность
сессии (session timeout). По истечении этого времени сервер доступа
обязан текущую сессию разорвать. Других способов повлиять на сессию у
RADIUS сервера нет.
Этого вполне достаточно в случае предоставления услуги временного
типа, когда существующий лицевой счет абонента используется для оплаты
этой единственной услуги. Если же предоставляемая услуга носит
объемный характер, либо она оказывается в рамках конвергентной
биллинговой системы, то на момент аутентификации пользователя
становится невозможным определить время, когда баланс учетной записи
иссякнет, а значит не может быть вычислена максимальная длительность
сессии.
В системе LANBilling эта проблема решена следующим образом: при
аутентификации пользователю выдается условно бесконечный таймаут
сессии. Если тарификация услуги осуществляется RADIUS агентом (он же
выполняет функции RADIUS сервера), то от сервера доступа в
обязательном порядке требуется поддержка промежуточных пакетов
эккаунтинга (alive updates). Наличие промежуточного эккаунтинга
позволяет RADIUS серверу поддерживать баланс абонента в актуальном
состоянии. Когда состояние лицевого счета достигнет отметки
блокирования доступа к услуге, агент, обслуживающий данную учетную
запись, запускает внешние скрипты, определяемые конфигурацией агента.
Сначала запускается скрипт vg_off для этой учетной записи.
Затем для каждой активной сессии (если таковые имеются) запускается
script_stop, призванный разорвать текущее соединение. В параметрах
скрипту script_stop передаются Session id, логин, выданный ip (в
случае VoIP RADIUS session id и login). Данный скрипт должен
реализовывать управление NAS'ом, вызвав принудительное завершение
сессии, используя переданные ему параметры. Подобный механизм
позоволяет также выполнить отключение сессии менеджером через
административную консоль, не производя блокировку учетной записи.
Применение внешних скриптов предоставляет необходимую гибкость в
работе с различными серверами доступа, которые должны поддерживать
какой-либо механизм внешнего управления (rsh, snmp, ssh, telnet, POD и
пр.).
2. Примеры конфигураций
Ниже приведены примеры скриптов принудительного разрыва сессии
(script_stop) для некоторых наиболее часто используемых серверов
доступа.
2.1 Cisco Systems
Пример конфигурации устройства с использованием RADIUS сервера:
!
aaa new-model
!
!
aaa authentication ppp default group radius
aaa authorization network default group radius
aaa accounting update newinfo periodic 1
aaa accounting network default start-stop group radius
!
radius-server host 192.168.0.2 auth-port 34009 acct-port 34008 key my_shared_se
cret
!
Маршрутизаторы cisco поддерживают множество механизмов внешнего
управления. Удобнее всего использовать rsh, snmp, POD.
2.1.1 rsh
!
no ip rcmd domain-lookup
ip rcmd rsh-enable
ip rcmd remote-host cisco_user 11 root enable
!
!
username cisco_user privilege 15 secret 5 XXXXXXXXX
!
!
access-list 11 permit 192.168.0.2
access-list 11 deny any
!
Скрипт, запускаемый АСР для непосредственного "сброса" сессии может
выглядить следующим образом:
#!/bin/sh
CISCO="192.168.0.1"
USER="cisco_user"
RSH="/usr/bin/rsh"
test -z "$1" && exit 1
VIRTUALINT=`/usr/bin/rsh -l $USER $CISCO show users | grep -i " $1 " | awk '{print $1}';`
Vi=`echo $VIRTUALINT | sed -e "s/[[:alpha:]]*\([[:digit:]]\{1,\}\)/\1/"`
test -z "$Vi" && exit 2
$RSH -l $USER $CISCO clear interface virtual-access $Vi
exit 0
2.1.2 snmp
Необходимые инструкции в конфигурации NAS
!
access-list 11 permit 192.168.0.2
access-list 11 deny any
!
snmp-server community snmp_passwd rw 11
!
Этот способ менее универсален, так как зависит от версии MIB.
Приведенный ниже скрипт тестировался на cisco-7500 IOS 12.3(7)T. Поиск
и разрыв нужной сессии производится по ip адресу (3ий параметр).
Скрипт прерывания сессии:
#!/bin/sh
SNMPWALK="/usr/local/bin/snmpwalk"
SNMPSET="/usr/local/bin/snmpset"
COMMUNITY="snmp_passwd"
CISCO="192.168.0.1"
USER_IP="$3"
test -z "$USER_IP" && exit 1
INT_NUM=`$SNMPWALK -On -v 1 -c $COMMUNITY $CISCO .1.3.6.1.2.1.4.21.1.2.$USER_IP | awk '{print $4}'`
test -z "$INT_NUM" && exit 1
SNMPSET -v 1 -c $COMMUNITY $CISCO .1.3.6.1.2.1.2.2.1.7.$INT_NUM i 2 >/dev/null 2>&1
exit 0
2.1.3 POD
Необходимые инструкции в конфигурации NAS
!
aaa pod server clients 192.168.0.2 auth-type any server-key pod_shared_secret
!
Скрипт для отправки RADIUS POD написан на языке perl. Для его работы
необходим модуль Authen::Radius, установить который можно следующим
образом:
#perl -MCPAN -e shell
cpan> install Authen::Radius
cpan> quit
Далее к установленному модулю Radius.pm необходимо применить следующий
патч:
############################# Radius.pm-pod.patch #############################
--- Radius.pm.orig 2006-04-18 19:11:59.739806592 +0400
+ Radius.pm 2006-04-18 19:08:19.624269240 +0400
@@ -30,7 +30,7 @@
@ISA = qw(Exporter);
@EXPORT = qw(ACCESS_REQUEST ACCESS_ACCEPT ACCESS_REJECT
- ACCOUNTING_REQUEST ACCOUNTING_RESPONSE ACCOUNTING_STATUS);
+ ACCOUNTING_REQUEST ACCOUNTING_RESPONSE ACCOUNTING_STATUS POD_REQUEST COA_REQUEST);
$VERSION = '0.12';
my (%dict_id, %dict_name, %dict_val, %dict_vendor_id, %dict_vendor_name );
@@ -53,6 +53,8 @@
use constant ACCOUNTING_REQUEST => 4;
use constant ACCOUNTING_RESPONSE => 5;
use constant ACCOUNTING_STATUS => 6;
+use constant POD_REQUEST => 40;
+use constant COA_REQUEST => 43;
sub new {
my $class = shift;
@@ -102,7 +104,7 @@
my $length = 20 + length($self->{'attributes'});
$self->set_error;
- if ($type == ACCOUNTING_REQUEST) {
+ if (($type == ACCOUNTING_REQUEST) || ($type == POD_REQUEST) || ($type == COA_REQUEST)) {
$self->{'authenticator'} = "\0" x 16;
$self->{'authenticator'} =
$self->calc_authenticator($type, $request_id, $length)
###############################################################################
#cd /usr/lib/perl5/site_perl/5.8.5/Authen/
Путь может отличаться взависимости от версии установленного perl
транслятора.
#patch -p0 < /path to patch/Radius.pm-pod.patch
Скрипт прерывания сессии:
#!/usr/bin/perl
use Authen::Radius;
my $POD_server='192.168.0.1:1700';
my $shared_secret='pod_shared_secret';
my $login = shift;
my $pass = shift;
my $ip = shift;
if ($ip=~/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/){
my $r = new Authen::Radius(Host => $POD_server, Secret => $shared_secret);
Authen::Radius->load_dictionary;
$r->add_attributes ({Name => 'Framed-IP-Address', Value => $ip});
$r->send_packet (POD_REQUEST) and $type = $r->recv_packet;
if( !defined $type ) {
# No responce from POD server
die();
}
}
2.2 Linux PoPToP
Не останавливаясь на конфигурации pptpd, стоит отметить, что отсылка
промежуточных пакетов эккаунтинга может регулироваться только RADIUS
сервером (в конфигурационных файлах pppd этого параметра нет).
LANBilling RADIUS агент всегда устанавливает интервал Alive-пакетов
равным 60 сек.
Скрипт прерывания сессии:
#!/bin/bash
USER_IP="$3"
PID_DIR=/var/run
test -z "$USER_IP" && exit 1
IF=`/sbin/ifconfig | grep -B 1 "${USER_IP} " | head -n1 | awk {'print $1'}`;
PID=`cat ${PID_DIR}/${IF}.pid 2>/dev/nul`;
test -z "${PID}" && exit 1
kill -INT ${PID};
exit 0;
2.3 FreeBSD mpd
Здесь для управления NAS'ом используется консоль mpd, поэтому
запускать mpd следует с дополнительными ключами: -a MHOST -c MPORT,
где MHOST и MPORT нужно заменить на прослушиваемые ip и порт
соответсвенно.
Скрипт прерывания сессии:
#!/usr/local/bin/bash
MHOST=127.0.0.1 # mpd host
MPORT=5555 # mpd telnet port
IP="$3";
test -z "$IP" && exit 1
for bundle in `echo "bundle" | /usr/bin/nc $MHOST $MPORT | grep Opened | awk '{print $1}'`;
do
if echo -e "bundle $bundle\\nshow iface" | /usr/bin/nc $MHOST $MPORT | grep "${IP}$" >/dev/null 2>&1
then
echo -e "bundle $bundle\\nclose phys" | /usr/bin/nc $MHOST $MPORT >/dev/null 2>&1
fi
done;
exit 0;
4. Asterisk + VoIP RADIUS
-------------------------
(решение описано здесь)
Скрипт прерывания сессии:
#!/usr/bin/perl
use strict;
use Asterisk::Manager;
use Digest::MD5 qw(md5_hex);
my $SessionID=shift;
my $astman = new Asterisk::Manager;
$astman->user('user');
$astman->secret('passwd');
$astman->host('127.0.0.1');
if( $astman->connect ) {
my @list=$astman->sendcommand(Action => 'Command', Command => 'show channels',2);
foreach (@list){
my $chan=$1 if $_ =~ /^(\S+\/\S+)\s.*$/;
if ($chan && (get_session_id($chan) eq $SessionID)){
my @resp=$astman->sendcommand(Action => 'Hangup', Channel => $chan,2);
}
}
$astman->disconnect;
}
sub get_session_id{
my $confid = uc(md5_hex(@_));
$confid =~ s/(\w{8})(\w{8})(\w{8})(\w{8})/$1 $2 $3 $4/;
return $confid;
}