====== Управление сетью на базе Extreame Summit 24i/48i с помошью telnet ======
свичи выступают в роли NAS
===== Логика работы системы =====
1. В зависимости от статуса абонента применить действие на порту
|Статус абонента|действие|
|Интернет отключен|отключить порт|
|Интернет включен|включить порт|
2. Задать шейпер
Если интернет включен то задать шейпер на порту вх/исх
Эти вещи делает скрипт автоматически по событиям использую протокол telnet и perl
===== Пути к файлам =====
Скачав дистрибутива MikBiLL начиная с версии 2.0.5
вы найдете скрипты в папке
/DISTR/primer/extreame
Рекомендуем скопировать файлы в папку скриптов админки
путь linux
/var/www/mikbill/admin/sys/scripts
путь bsd
/usr/local/www/mikbill/admin/sys/scripts
===== описание файлов =====
|switches_summit_one.pl|скрипт выполняет действие на кокретном абоненте|
|switches_summit.pl|скрипт выполняет действие на всей сети|
===== Настройка =====
Установите модули на перл или средствами вашей OS или через CPAN
выполнить под root
perl -MCPAN -e 'install DBI DBD::mysql Net::Telnet Data::Dumper'
овтетить на все вопросы и установить модули.
В обоих файлах для начала задайте даныне для доступа к вашей БД с MIkBiLL
Строки 23,24,25,26
в обоих файлах
switches_summit_one.pl
switches_summit.pl
my $sql_db='mikbill';
my $sql_login='mikbill';
my $sql_pass='password';
my $sql_host='localhost';
Для скрипта switches_summit_one.pl
В строке 183 укажите
ID типа устройства на котором вы будете запускать данный функционал
Админка-Настройки-Справочники-Типы устройств
Пример для типа устройств с ID=7
if ($swtypeid_input=="7") {
по необходимости замените на Ваш номер
Для скрипта switches_summit.pl
В строке 178 укажите
ID типа устройства на котором вы будете запускать данный функционал
Админка-Настройки-Справочники-Типы устройств
Пример для типа устройств с ID=7
my $sql="SELECT nameswitch, ip, login, pass , swtypeid , swid FROM $switches WHERE swtypeid = '7'";
по необходимости замените на Ваш номер
===== Ввод в эксплуатацию =====
После настройки осталось запустить это в работу.
1. Запускаем скрипт switches_summit.pl в cron после снятия абонплат 00:30 будет вполне нормальным временем
2. заносим во все скрипты событий следующие строки ( в конец файла)
для linux
cd /var/www/mikbill/admin/sys/scripts
./switches_summit_one.pl $3 $4 $7 $1 &>/dev/null
для bsd
cd /usr/local/www/mikbill/admin/sys/scripts
./switches_summit_one.pl $3 $4 $7 $1 &>/dev/null
===== Исходник switches_summit_one.pl =====
#!/usr/bin/perl
use Net::Telnet;
use DBI;
use strict;
use locale;
use Data::Dumper;
use POSIX;
setlocale(LC_ALL, 'C');
# sw_ip = $ARGV[0];
# sw_port = $ARGV[1];
my $swtypeid_input = $ARGV[2];
my $debug=1;
my $print_switch=1;
my $do_nothing=0;
my $mb=1024;
my $dbh;
my $sql_db='mikbill';
my $sql_login='mikbill';
my $sql_pass='password';
my $sql_host='localhost';
my $acct_table1 = "radacct";
my $acct_table2 = "radacct";
my $packets = "packets";
my $users = "users";
my $switches = "switches";
my $switche_type = "switche_type";
my $switch_uplink = "switch_uplink";
sub sql {
my $dsn = 'DBI:mysql:'.$sql_db.':'.$sql_host;
my $dbh=DBI->connect($dsn, $sql_login, $sql_pass) or die "Couldn't connect to database: " . DBI->errstr;
return $dbh;
}
$dbh=&sql;
sub get_switch_type {
my $sql="SELECT swtypeid,numports FROM $switche_type WHERE 1";
my $sth = $dbh->prepare($sql);
$sth->execute;
my %switchtype_ports;
while (my @row = $sth->fetchrow_array)
{
$switchtype_ports{$row[0]}=$row[1];
}
$sth->finish;
return %switchtype_ports;
};
my %switchtype_ports=&get_switch_type;
my $check_switch_uplink_by_swid_port = sub {
my ($dbh,$swid,$port) = @_;
my $sql="SELECT port FROM $switch_uplink WHERE swid=$swid and port=$port";
my $sth = $dbh->prepare($sql);
$sth->execute;
my @row = $sth->fetchrow_array;
$sth->finish;
return @row;
};
my $check_tarif_by_gid = sub {
my ($dbh,$gid) = @_;
my $sql="SELECT gid,speed_rate,speed_burst FROM $packets WHERE gid=$gid";
my $sth = $dbh->prepare($sql);
$sth->execute;
my @row = $sth->fetchrow_array;
$sth->finish;
return @row;
};
my $check_user_by_swid_port = sub {
my ($dbh,$swid,$port) = @_;
my $sql="SELECT uid,deposit,credit,blocked,gid,speed_rate,speed_burst FROM $users WHERE swid=$swid and switchport=port";
my $sth = $dbh->prepare($sql);
$sth->execute;
my @row = $sth->fetchrow_array;
$sth->finish;
return @row;
};
my $set_port_sw_200_down = sub {
my ($t,$port) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('disable ports '.$port);
}
if ($debug==1){
print $port." user not found\n";
}
};
my $do_del_rate_up = sub {
my ($t,$port) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('delete rate-limit net_up_'.$port);
}
};
my $do_del_rate_down = sub {
my ($t,$port) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('delete rate-limit net_down_'.$port);
}
};
my $set_port_sw_200_rate_up = sub {
my ($t,$port,$res_speed_up) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('create rate-limit net_up_'.$port.' access-mask net_up port '.$port.' permit limit '.$res_speed_up.'exceed-action drop');
}
};
my $set_port_sw_200_rate_down = sub {
my ($t,$port,$res_speed_down) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('create rate-limit net_down_'.$port.' access-mask net_down egress-port '.$port.' port 25 permit limi '.$res_speed_down.' exceed-action drop');
}
};
my $set_port_sw_200_up = sub {
my ($t,$port) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('enable ports '.$port);
}
if ($debug==1){
print $port." user found\n";
}
};
my $create_mask_sw_200 = sub {
my ($t) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('delete access-mask net_up');
$t->waitfor('/#:/i');
$t->print('delete access-mask net_down ');
$t->waitfor('/#:/i');
$t->print('create access-mask net_up port');
$t->waitfor('/#:/i');
$t->print('create access-mask net_down egress-port port');
}
};
my $get_switch_uplink_by_swid = sub {
my ($dbh,$swid) = @_;
my $sql="SELECT port FROM $switch_uplink WHERE swid=$swid";
my $sth = $dbh->prepare($sql);
$sth->execute;
my %switchtype_ports_uplink;
my $i=0;
while (my @row = $sth->fetchrow_array)
{
$switchtype_ports_uplink{$i}=$row[0];
$i=$i+1;
}
$sth->finish;
return %switchtype_ports_uplink;
};
if ($swtypeid_input=="7") {
my $sql="SELECT nameswitch, ip, login, pass , swtypeid , swid FROM $switches WHERE ip ='".$ARGV[0]."'";
my $sth = $dbh->prepare($sql);
$sth->execute;
my @row = $sth->fetchrow_array;
my $swtypeid = $row[4] ;
my $swid = $row[5];
my $sw_ip = $row[1];
my $swtypeid = $row[4] ;
my $max_port_switch=$switchtype_ports{$swtypeid};
if ($print_switch==1){
print "ip: $sw_ip\tnameswitch: $row[0]\tswid:$swid\tports:$max_port_switch\t";
}
#Telnet to dev
my $file = "/home/log/$row[1].log";
my $t = new Net::Telnet(Timeout => 1, Telnetmode => 0, Errmode => "return", Input_log => $file);
$t->open(Host => $sw_ip);
$t->waitfor('/login:/i');
$t->print($row[2]);
$t->waitfor('/password:/i');
$t->print($row[3]);
if ($print_switch==1){
print "OK\n";
}
my $port_current=$ARGV[1];
my $check_port=$check_switch_uplink_by_swid_port->($dbh,$swid,$port_current);
if ($check_port==0) {
my @check_user=$check_user_by_swid_port->($dbh,$swid,$port_current);
if (@check_user==0) {
$set_port_sw_200_down->($t,$port_current);
}else{
my $uid=$check_user[0];
my $deposit=$check_user[1];
my $credit=$check_user[2];
my $blocked=$check_user[3];
my $gid=$check_user[4];
my $user_speed_up=$check_user[5]/$mb;
my $user_speed_down=$check_user[6]/$mb;
my @check_tarif_by_gid=$check_tarif_by_gid->($dbh,$gid);
my $tarif_speed_up=$check_tarif_by_gid[1]/$mb;
my $tarif_speed_down=$check_tarif_by_gid[2]/$mb;
$user_speed_up=sprintf("%.0f",$user_speed_up);
$user_speed_down=sprintf("%.0f",$user_speed_down);
$tarif_speed_up=sprintf("%.0f",$tarif_speed_up);
$tarif_speed_down=sprintf("%.0f",$tarif_speed_down);
my $res_speed_up=0;
my $res_speed_down=0;
if ($user_speed_up!=0) {
$res_speed_up=$user_speed_up;
}else{
$res_speed_up=$tarif_speed_up;
}
if ($user_speed_down!=0) {
$res_speed_down=$user_speed_down;
}else{
$res_speed_down=$tarif_speed_down;
}
# print "$res_speed_up \n";
# print "$res_speed_down \n";
if ($blocked==1) {
$set_port_sw_200_down->($t,$port_current);
}else{
if (($deposit+$credit)<0) {
$set_port_sw_200_down->($t,$port_current);
}else{
$set_port_sw_200_up->($t,$port_current);
$do_del_rate_up->($t,$port_current);
$do_del_rate_down->($t,$port_current);
if ($res_speed_up!=0) {
$set_port_sw_200_rate_up->($t,$port_current,$res_speed_up);
}
if ($res_speed_down!=0) {
$set_port_sw_200_rate_down->($t,$port_current,$res_speed_down);
}
}
}
}
}
$sth->finish;
}
$dbh->disconnect;
===== Исходник switches_summit.pl =====
#!/usr/bin/perl
use Net::Telnet;
use DBI;
use strict;
use locale;
use Data::Dumper;
use POSIX;
setlocale(LC_ALL, 'C');
my $debug=0;
my $print_switch=1;
my $do_nothing=0;
my $mb=1024;
my $dbh;
my $sql_db='mikbill';
my $sql_login='mikbill';
my $sql_pass='password';
my $sql_host='localhost';
my $acct_table1 = "radacct";
my $acct_table2 = "radacct";
my $packets = "packets";
my $users = "users";
my $switches = "switches";
my $switche_type = "switche_type";
my $switch_uplink = "switch_uplink";
sub sql {
my $dsn = 'DBI:mysql:'.$sql_db.':'.$sql_host;
my $dbh=DBI->connect($dsn, $sql_login, $sql_pass) or die "Couldn't connect to database: " . DBI->errstr;
return $dbh;
}
$dbh=&sql;
sub get_switch_type {
my $sql="SELECT swtypeid,numports FROM $switche_type WHERE 1";
my $sth = $dbh->prepare($sql);
$sth->execute;
my %switchtype_ports;
while (my @row = $sth->fetchrow_array)
{
$switchtype_ports{$row[0]}=$row[1];
}
$sth->finish;
return %switchtype_ports;
};
my %switchtype_ports=&get_switch_type;
my $check_switch_uplink_by_swid_port = sub {
my ($dbh,$swid,$port) = @_;
my $sql="SELECT port FROM $switch_uplink WHERE swid=$swid and port=$port";
my $sth = $dbh->prepare($sql);
$sth->execute;
my @row = $sth->fetchrow_array;
$sth->finish;
return @row;
};
my $check_tarif_by_gid = sub {
my ($dbh,$gid) = @_;
my $sql="SELECT gid,speed_rate,speed_burst FROM $packets WHERE gid=$gid";
my $sth = $dbh->prepare($sql);
$sth->execute;
my @row = $sth->fetchrow_array;
$sth->finish;
return @row;
};
my $check_user_by_swid_port = sub {
my ($dbh,$swid,$port) = @_;
my $sql="SELECT uid,deposit,credit,blocked,gid,speed_rate,speed_burst FROM $users WHERE swid=$swid and switchport=$port";
my $sth = $dbh->prepare($sql);
$sth->execute;
my @row = $sth->fetchrow_array;
$sth->finish;
return @row;
};
my $set_port_sw_200_down = sub {
my ($t,$port) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('disable ports '.$port);
}
if ($debug==1){
print $port." user not found\n";
}
};
my $do_del_rate_up = sub {
my ($t,$port) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('delete rate-limit net_up_'.$port);
}
};
my $do_del_rate_down = sub {
my ($t,$port) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('delete rate-limit net_down_'.$port);
}
};
my $set_port_sw_200_rate_up = sub {
my ($t,$port,$res_speed_up) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('create rate-limit net_up_'.$port.' access-mask net_up ethertype 0x800 dest-ip 0.0.0.0 / 0 port '.$port.' permit limit '.$res_speed_up.' exceed-action drop');
}
};
my $set_port_sw_200_rate_down = sub {
my ($t,$port,$res_speed_down) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('create rate-limit net_down_'.$port.' access-mask net_down egress-port '.$port.' port 25 permit limit '.$res_speed_down.' exceed-action drop');
}
};
my $set_port_sw_200_up = sub {
my ($t,$port) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('enable ports '.$port);
}
if ($debug==1){
print $port." user found\n";
}
};
my $create_mask_sw_200 = sub {
my ($t) = @_;
if ($do_nothing==0) {
$t->waitfor('/#:/i');
$t->print('delete access-mask net_up');
$t->waitfor('/#:/i');
$t->print('delete access-mask net_down ');
$t->waitfor('/#:/i');
$t->print('create access-mask net_up ethertype dest-ip / 0 precedence 100');
$t->waitfor('/#:/i');
$t->print('create access-mask net_down egress-port precedence 100');
}
};
my $get_switch_uplink_by_swid = sub {
my ($dbh,$swid) = @_;
my $sql="SELECT port FROM $switch_uplink WHERE swid=$swid";
my $sth = $dbh->prepare($sql);
$sth->execute;
my %switchtype_ports_uplink;
my $i=0;
while (my @row = $sth->fetchrow_array)
{
$switchtype_ports_uplink{$i}=$row[0];
$i=$i+1;
}
$sth->finish;
return %switchtype_ports_uplink;
};
my $sql="SELECT nameswitch, ip, login, pass , swtypeid , swid FROM $switches WHERE swtypeid = '7'";
my $sth = $dbh->prepare($sql);
$sth->execute;
while (my @row = $sth->fetchrow_array)
{
my $swtypeid = $row[4] ;
my $swid = $row[5];
my $sw_ip = $row[1];
my $swtypeid = $row[4] ;
my $max_port_switch=$switchtype_ports{$swtypeid};
if ($print_switch==1){
print "ip: $sw_ip\tnameswitch: $row[0]\tswid:$swid\tports:$max_port_switch\t";
}
#Telnet to dev
my $file = "/home/log/$row[1].log";
my $t = new Net::Telnet(Timeout => 1, Telnetmode => 0, Errmode => "return", Input_log => $file);
$t->open(Host => $sw_ip);
$t->waitfor('/login:/i');
$t->print($row[2]);
$t->waitfor('/password:/i');
$t->print($row[3]);
if ($print_switch==1){
print "OK\n";
}
# print "test1\n";
# my %switchtype_ports_uplink=$get_switch_uplink_by_swid->($dbh,$swid);
$create_mask_sw_200->($t);
my $port_current=1;
while ( $port_current <= $max_port_switch)
{
my $check_port=$check_switch_uplink_by_swid_port->($dbh,$swid,$port_current);
if ($check_port==0) {
my @check_user=$check_user_by_swid_port->($dbh,$swid,$port_current);
if (@check_user==0) {
$set_port_sw_200_down->($t,$port_current);
}else{
my $uid=$check_user[0];
my $deposit=$check_user[1];
my $credit=$check_user[2];
my $blocked=$check_user[3];
my $gid=$check_user[4];
my $user_speed_up=$check_user[5]/$mb;
my $user_speed_down=$check_user[6]/$mb;
my @check_tarif_by_gid=$check_tarif_by_gid->($dbh,$gid);
my $tarif_speed_up=$check_tarif_by_gid[1]/$mb;
my $tarif_speed_down=$check_tarif_by_gid[2]/$mb;
$user_speed_up=sprintf("%.0f",$user_speed_up);
$user_speed_down=sprintf("%.0f",$user_speed_down);
$tarif_speed_up=sprintf("%.0f",$tarif_speed_up);
$tarif_speed_down=sprintf("%.0f",$tarif_speed_down);
my $res_speed_up=0;
my $res_speed_down=0;
if ($user_speed_up!=0) {
$res_speed_up=$user_speed_up;
}else{
$res_speed_up=$tarif_speed_up;
}
if ($user_speed_down!=0) {
$res_speed_down=$user_speed_down;
}else{
$res_speed_down=$tarif_speed_down;
}
# print "$res_speed_up \n";
# print "$res_speed_down \n";
if ($blocked==1) {
$set_port_sw_200_down->($t,$port_current);
}else{
if (($deposit+$credit)<0) {
$set_port_sw_200_down->($t,$port_current);
}else{
$set_port_sw_200_up->($t,$port_current);
$do_del_rate_up->($t,$port_current);
$do_del_rate_down->($t,$port_current);
if ($res_speed_up!=0) {
$set_port_sw_200_rate_up->($t,$port_current,$res_speed_up);
}
if ($res_speed_down!=0) {
$set_port_sw_200_rate_down->($t,$port_current,$res_speed_down);
}
}
}
}
}
$port_current=$port_current+1;
}
# my $result=$t->getline;
# print $result;
}
$sth->finish;
$dbh->disconnect;
===== На последок =====
Никто не мешает поправить скрипт под ваше оборудование и использовать в своих целях
Обсуждаем на [[http://www.mikbill.ru/forums/forum/9-nas-network-access-server/|форуме]]