shaper.php
Код: Выделить всё
<?php
require("config.inc.php");
require("Database.class.php");
$db = new Database(DB_SERVER, DB_USER, DB_PASS, DB_DATABASE);
$db->connect();
function sendcisco($command_clear,$command_add){
//ПОДКЛЮЧАЕМЫЕ МОДУЛИ
require 'Cisco.php';
///////////////////////////////////////////////////////////////////
//КОНФИГРУРАЦИЯ
$cisco_hostname = '11.11.11.11'; //ХОСТ
$cisco_username = '1'; //ЮЗЕР
$cisco_password = 'pass'; //ПАРОЛЬ
$cisco_enpasswd = 'enablepassword'; //ПАРОЛЬ НА ENABLE
///////////////////////////////////////////////////////////////////
//КОННЕКТИМСЯ
$cisco = new Cisco($cisco_hostname,$cisco_password,$cisco_username);
$cisco->connect();
$cisco -> enable($cisco_enpasswd);
///////////////////////////////////////////////////////////////////
$cisco -> sendcommand($command_clear,$command_add);
$cisco -> disable();
sleep(3);
}
function gethourtraff($db) {
//ОПРЕДЕЛЯЕМ ТЕКУЩИЙ ПРОМЕЖУТОК ВРЕМЕНИ
$time_now=time();
$time_past=($time_now-3600);
$sql = 'SELECT'
. ' uname, account_id, SUM(bytes) bytes,'
. ' inet_ntoa(case when ipid > 0 then ipid else 4294967296+ipid end) ipid'
. ' FROM discount_transactions_iptraffic_all'
. ' INNER JOIN ip_groups'
. ' ON discount_transactions_iptraffic_all.ipid = ip_groups.ip AND ip_groups.is_deleted = 0'
. ' WHERE discount_transactions_iptraffic_all.discount_date>='.$time_past
. ' AND discount_transactions_iptraffic_all.discount_date <='.$time_now
. ' AND discount_transactions_iptraffic_all.t_class="1"'
. ' GROUP BY account_id,ipid'
. ' ORDER BY account_id,ipid';
$rows = $db->query($sql);
$sql_delete = "DELETE FROM `".TABLE_TEMP."` WHERE 1=1";
$db->query($sql_delete);
while ($record = $db->fetch_array($rows)) {
$data['login'] = $record['uname'];
$data['ip'] = $record['ipid'];
$data['downloaded'] = $record['bytes']/1048576; // query_insert() will auto escape it for us
$db->query_insert("myshaper_temp", $data);
}
}
function shape_user($db,$username,$ip,$acl_new,$acl_new_name,$acl_old,$acl_old_name,$sp_new,$sp_old,$next_speed){
print("SHAPING USER ".$username." FROM ".$sp_old." TO ".$sp_new."\n");
print("---------->>> clear access-template ".$acl_old." ".$acl_old_name." any host ".$ip."\n");
print("---------->>> access-template ".$acl_new." ".$acl_new_name." any host ".$ip."\n");
$command_clear = "clear access-template ".$acl_old." ".$acl_old_name." any host ".$ip;
$command_add = "access-template ".$acl_new." ".$acl_new_name." any host ".$ip;
sendcisco($command_clear,$command_add);
print("CHANGING CURRENT USER SPEED TO ".$next_speed." IN DATABASE\n");
$data['currspeed'] = $next_speed;
$db->query_update(TABLE_USERS, $data, "login='".$username."'");
}
function unshape_user($db,$username,$ip,$acl_new,$acl_new_name,$acl_old,$acl_old_name,$sp_new,$sp_old,$next_speed){
print("UNSHAPING USER ".$username." FROM ".$sp_old." TO ".$sp_new."\n");
print("---------->>> clear access-template ".$acl_old." shaper1 any host ".$ip."\n");
print("---------->>> access-template ".$acl_new." shaper1 any host ".$ip."\n");
$command_clear = "clear access-template ".$acl_old." ".$acl_old_name." any host ".$ip;
$command_add = "access-template ".$acl_new." ".$acl_new_name." any host ".$ip;
sendcisco($command_clear,$command_add);
print("CHANGING CURRENT USER SPEED TO ".$next_speed." IN DATABASE\n");
$data['currspeed'] = $next_speed;
$db->query_update(TABLE_USERS, $data, "login='".$username."'");
}
function checkusercurrenttraff($db,$username){
$sql_check_user_traff = 'SELECT * FROM `myshaper_temp` WHERE login = \''.$username.'\'';
$rows = $db->query($sql_check_user_traff);
while ($record = $db->fetch_array($rows)) {
$data['ip'] = $record['ip'];
$data['downloaded'] = $record['downloaded'];
}
return $data;
}
function checkuser($db,$username){
$sql_check = 'SELECT * FROM `myshaper_users` WHERE login = \''.$username.'\'';
$rows = $db->query($sql_check);
while ($record = $db->fetch_array($rows)) {
$data['login'] = $record['login'];
$data['currspeed'] = $record['currspeed'];
$data['lim0'] = $record['lim0'];
$data['sp0'] = $record['sp0'];
$data['acl0'] = $record['acl0'];
$data['acl0name'] = $record['acl0name'];
$data['lim1'] = $record['lim1'];
$data['sp1'] = $record['sp1'];
$data['acl1'] = $record['acl1'];
$data['acl1name'] = $record['acl1name'];
$data['lim2'] = $record['lim2'];
$data['sp2'] = $record['sp2'];
$data['acl2'] = $record['acl2'];
$data['acl2name'] = $record['acl2name'];
print("+++++++++++++++++++++++++++++++++++++++++++++\n");
print("CHECKING USER ".$username." ...\n");
if ($data['currspeed'] == 'sp0'):
print("CURRENT USER SPEED: ".$data['sp0']." (".$data['currspeed'].")\n");
print("TRAFFIC LIMIT FOR USER ON SPPED-0 IS: ".$data['lim0']." MEGABYTES\n");
$ip_downloaded = checkusercurrenttraff($db,$username);
print("USER DOWNLOADED IN THIS HOUR: ".$ip_downloaded['downloaded']."\n");
print("USER IP ADDRESS IS: ".$ip_downloaded['ip']."\n");
if ($ip_downloaded['downloaded'] > $data['lim0']):
print("+0+ USER DOWNLOADED _".$ip_downloaded['downloaded']."_ THAT IS MORE THAN CURRENT LIMIT ".$data['lim0']." +0+\n");
shape_user($db,$username,$ip_downloaded['ip'],$data['acl1'],$data['acl1name'],$data['acl0'],$data['acl0name'],$data['sp1'],$data['sp0'],'sp1');
else:
print("-0- USER DOWNLOADED _".$ip_downloaded['downloaded']."_ THAT IS OK!!! - CURRENT LIMIT ".$data['lim0']." -0-\n");
endif;
endif;
if ($data['currspeed'] == 'sp1'):
print("CURRENT USER SPEED: ".$data['sp1']." (".$data['currspeed'].")\n");
print("TRAFFIC LIMIT FOR USER ON SPPED-1 IS: ".$data['lim1']." MEGABYTES\n");
$ip_downloaded = checkusercurrenttraff($db,$username);
print("USER DOWNLOADED IN THIS HOUR: ".$ip_downloaded['downloaded']."\n");
print("USER IP ADDRESS IS: ".$ip_downloaded['ip']."\n");
if ($ip_downloaded['downloaded'] > $data['lim1']):
print("+1+ USER DOWNLOADED _".$ip_downloaded['downloaded']."_ THAT IS MORE THAN CURRENT LIMIT ".$data['lim1']." +1+\n");
shape_user($db,$username,$ip_downloaded['ip'],$data['acl2'],$data['acl2name'],$data['acl1'],$data['acl1name'],$data['sp2'],$data['sp1'],'sp2');
else:
print("-1- USER DOWNLOADED _".$ip_downloaded['downloaded']."_ THAT IS GOOD!!! - CURRENT LIMIT ".$data['lim1']." -1-\n");
unshape_user($db,$username,$ip_downloaded['ip'],$data['acl0'],$data['acl0name'],$data['acl1'],$data['acl1name'],$data['sp0'],$data['sp1'],'sp0');
endif;
endif;
if ($data['currspeed'] == 'sp2'):
print("CURRENT USER SPEED: ".$data['sp2']." (".$data['currspeed'].")\n");
print("TRAFFIC LIMIT FOR USER ON SPPED-2 IS: ".$data['lim2']." MEGABYTES\n");
$ip_downloaded = checkusercurrenttraff($db,$username);
print("USER DOWNLOADED IN THIS HOUR: ".$ip_downloaded['downloaded']."\n");
print("USER IP ADDRESS IS: ".$ip_downloaded['ip']."\n");
if ($ip_downloaded['downloaded'] > $data['lim2']):
print("+2+ USER IS SUPERDOWNLOADER _".$ip_downloaded['downloaded']."_ CONTINUING USING _LOWEST_ SPEED ".$data['lim2']." +2+\n");
else:
print("-2- USER DOWNLOADED _".$ip_downloaded['downloaded']."_ THAT IS GOOD!!! - CURRENT LIMIT ".$data['lim2']." -2-\n");
unshape_user($db,$username,$ip_downloaded['ip'],$data['acl1'],$data['acl1name'],$data['acl2'],$data['acl2name'],$data['sp1'],$data['sp2'],'sp1');
endif;
endif;
}
print("+++++++++++++++++++++++++++++++++++++++++++++\n");
}
gethourtraff($db);
checkuser($db,'test');
$db->close();
?>
Код: Выделить всё
<?php
class Cisco
{
private $_hostname;
private $_password;
private $_username;
private $_connection;
private $_data;
private $_timeout;
private $_prompt;
public function getUserTraffic($user_interface)
{
$this->_send("sh int ".$user_interface." | in underruns");
$this->_readTo($this->_prompt);
$result = array();
$this->_data = explode("\r\n", $this->_data);
array_pop($this->_data);
$temp = $this->_data[1];
$temp = sscanf($temp, "%d %s %s %d %s %d %s");
$bytes = $temp[3];
$megabytes = $bytes/1048576;
//TEST
$string = $user_interface.":".$megabytes."\n";
return $string;
//return $megabytes;
}
public function sendcommand($command_clear,$command_add){
$this->_send($command_clear);
sleep(1);
$this->_send($command_add);
}
public function __construct($hostname, $password, $username = "", $timeout = 10)
{
$this->_hostname = $hostname;
$this->_password = $password;
$this->_username = $username;
$this->_timeout = $timeout;
} // __construct
/**
* Подключаемся к устройству
*/
public function connect()
{
$this->_connection = fsockopen($this->_hostname, 23, $errno, $errstr, $this->_timeout);
if ($this->_connection === false) {
die("Error: Connection Failed for $this->_hostname\n");
} // if
stream_set_timeout($this->_connection, $this->_timeout);
$this->_readTo(':');
if (substr($this->_data, -9) == 'Username:') {
$this->_send($this->_username);
$this->_readTo(':');
} // if
$this->_send($this->_password);
$this->_prompt = '>';
$this->_readTo($this->_prompt);
if (strpos($this->_data, $this->_prompt) === false) {
fclose($this->_connection);
die("Error: Authentication Failed for $this->_hostname\n");
} // if
} // connect
/**
* Закрываем соединение
*/
public function close()
{
$this->_send('quit');
fclose($this->_connection);
} // close
/**
* Даём команду в терминал
*/
private function _send($command)
{
fputs($this->_connection, $command . "\r\n");
} // _send
/**
* Читаем терминал
*
*/
private function _readTo($char)
{
// Reset $_data
$this->_data = "";
while (($c = fgetc($this->_connection)) !== false) {
$this->_data .= $c;
if ($c == $char[0]) break;
if ($c == '-') {
// Continue at --More-- prompt
if (substr($this->_data, -8) == '--More--') fputs($this->_connection, ' ');
} // if
} // while
// Remove --More-- and backspace
$this->_data = str_replace('--More--', "", $this->_data);
$this->_data = str_replace(chr(8), "", $this->_data);
// Set $_data as false if previous command failed.
if (strpos($this->_data, '% Invalid input detected') !== false) $this->_data = false;
} // _readTo
/**
* заходим в привелегированный режим Enable
*
*
*/
public function enable($password)
{
$result = false;
if ($this->_prompt != '#') {
$this->_send('enable');
$this->_readTo(':');
$this->_send($password);
if ($this->_data !== false) {
$this->_prompt = '#';
$result = true;
} // if
$this->_readTo($this->_prompt);
return $result;
} // if
} // enable
/**
* Disable - выходим из Enable
*/
public function disable()
{
if ($this->_prompt == '#') {
$this->_send('disable');
$this->_prompt = '>';
$this->_readTo($this->_prompt);
} // if
} // disable
/**
* Ping
*/
public function ping($host)
{
$this->_send("ping $host");
$this->_readTo($this->_prompt);
$this->_data = explode("\r\n", $this->_data);
for ($i = 0; $i < 3; $i++) array_shift($this->_data);
array_pop($this->_data);
$this->_data = implode("\n", $this->_data);
return $this->_data;
} // ping
public function getUsers()
{
$this->_send('show users');
$this->_readTo($this->_prompt);
$result = array();
$this->_data = explode("\r\n", $this->_data);
array_pop($this->_data);
foreach ($this->_data as $entry) {
if (preg_match('/Bundle/i',$entry)) {
$temp = sscanf($entry, "%s %s %s %s %s %s");
$entry = array();
$entry['idle'] = $temp[4];
$entry['ip'] = $temp[5];
} else {
$temp = sscanf($entry, "%s %s %s %s %s");
$entry = array();
$entry['idle'] = $temp[3];
$entry['ip'] = $temp[4];
}//if
$entry['interface'] = $temp[0];
$entry['username'] = $temp[1];
if (strstr($entry['ip'],"10.1.")) {
$entry['uplink'] = "USI";
} else {
$entry['uplink'] = "RTK";
}//if
if (preg_match('/u\d\d/i',$entry['username'])) {
$entry['client_type'] = "HOME";
} else {
$entry['client_type'] = "CORPORATE";
}//if
if ($entry['idle'] != 'Idle' && $entry['ip'] != '' && $entry['ip'] != 'Idle') {
array_push($result, $entry);
} //if
} // foreach
$this->_data = $result;
return $this->_data;
}
public function getUsersBand()
{
$this->_send('show int summary | in Virtual-Acc');
$this->_readTo($this->_prompt);
$result = array();
$this->_data = explode("\r\n", $this->_data);
array_pop($this->_data);
foreach ($this->_data as $entry) {
if (preg_match('/\*/i',$entry)) {
$temp = sscanf($entry, " * %s %s %s %s %s %s %s %s %s %s");
$temp[0] = str_replace("Virtual-Access","Vi",$temp[0]);
$gotovo[$temp[0]] = $temp[7];
} else {
$temp = sscanf($entry, " %s %s %s %s %s %s %s %s %s %s");
$temp[0] = str_replace("Virtual-Access","Vi",$temp[0]);
$gotovo[$temp[0]] = $temp[7];
}
} // foreach
//$this->_data = ($result);
//print_r($gotovo);
return $gotovo;
}
public function getUsersTraff()
{
$this->_send('show int');
$this->_readTo($this->_prompt);
//print_r($this->_data);
$result = array();
//$this->_data = explode("\r\n", $this->_data);
preg_match_all('/Virtual-Access(\d*).*?\d*\spackets\soutput.*?(\d*)\sbytes.*?transitions/ims',$this->_data,$users_downloaded);
/* for ($i=0;$i<count($testarr[1]);$i++) {
$testarr[1][$i]="Vi".$testarr[1][$i];
print($testarr[1][$i].":".$testarr[2][$i]."\n");
}
*/
$users_summary_downloaded = 0;
for ($i=0;$i<count($users_downloaded[1]);$i++) {
$users_downloaded[1][$i]="Vi".$users_downloaded[1][$i];
$user_interface=$users_downloaded[1][$i];
$user_downl=$users_downloaded[2][$i];
$users_downloaded_final[$user_interface]=$user_downl;
$users_summary_downloaded=$users_summary_downloaded+$users_summary_downloaded;
}
$users_downloaded_final['summary']=$users_summary_downloaded;
return $users_downloaded_final;
}
} // Cisco
//
СОЗДАЕМ БАЗЫ ДАННЫХ:
Код: Выделить всё
CREATE TABLE `myshaper_temp` (
`id` int(11) NOT NULL auto_increment,
`login` varchar(16) NOT NULL,
`ip` varchar(15) NOT NULL,
`downloaded` int(11) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `myshaper_users` (
`id` int(11) NOT NULL auto_increment,
`login` varchar(16) NOT NULL,
`sp0` int(11) NOT NULL,
`lim0` int(11) NOT NULL,
`acl0` int(11) NOT NULL,
`acl0name` varchar(12) NOT NULL,
`sp1` int(11) NOT NULL,
`lim1` int(11) NOT NULL,
`acl1` int(11) NOT NULL,
`acl1name` varchar(12) NOT NULL,
`sp2` int(11) NOT NULL,
`lim2` int(11) NOT NULL,
`acl2` int(11) NOT NULL,
`acl2name` varchar(12) NOT NULL,
`currspeed` varchar(3) NOT NULL default 'sp0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Создаём соотв. акцесс листы, например:
access-list 180 dynamic speed672 permit ip any any
access-list 181 dynamic speed448 permit ip any any
access-list 182 dynamic speed339 permit ip any any
на интерфейсе циски, на котором сидят пользователи создаём акцесс-группы, соответствующие заданным акцесс листам:
rate-limit output access-group 180 672000 84000 84000 conform-action transmit exceed-action drop
rate-limit output access-group 181 448000 56000 56000 conform-action transmit exceed-action drop
rate-limit output access-group 182 328000 42000 42000 conform-action transmit exceed-action drop
-----------------------------------
В отличии от dynashape, скрипт позволяет лимитировать трафик по загрузке "в течении текущего промежутка времени", не скидывая лимиты по окончанию периода. Конечно, требует доработки. Можно дописать шейпинг в зависимости от загрузки канала, итд.
[/b]