Страница 1 из 1

разделение трафика на мир/ua-ix

Добавлено: Пн окт 05, 2009 4:11 pm
star
FreeBsd 7.2+abills_0.42+exppp+rlm_perl
Собственно сабж. Есть список сетей порядка 1635 штук, которые если добавлять через веб морду заливается но криво. т.е. вместо 1635 сетей заводит 3700 и вылетает с обибкой"[1] (Wrong Exppp date '91.209.64.'; )"... Как я понимаю это баг, и чинить его автор в этой ветке уже не будет.

Ребят, подскажите алгоритм работы данного механизма. Откуда биллинг берет данные для создания правил в ipfw из фала /usr/abills/cgi-bin/admin/nets/2.nets (как пример) или из базы ??? Если уж использует ipfw, то может его лучше реализовать таблицами ??? Да и в веб-морде было-бы наглядней, таблица такая-то, а не список в 3000 сетей.

Re: разделение трафика на мир/ua-ix

Добавлено: Пн окт 05, 2009 4:55 pm
sopov
Правильнее было бы через таблицы, да и exppp это не лучший выбор - смотрите в сторону mpd. А вообще хватит делить инет на мир и киевскую локалку с Леонтовича 9... Интернет это ведь всетаки всемирная сеть - дайте людям нормальный мир...

Re: разделение трафика на мир/ua-ix

Добавлено: Пн окт 05, 2009 8:05 pm
star
Мир стоит денег, а как Вы выразились "киевская локалка" в к оторую входит куча операторов идет практически на шару, и мея канал в 1гиг вобщем-то почему-бы и не отдать людям нормальный трафик оттуда. за те-же деньги. ;)
Что касается мпд5, я раньше на нем строил, а потом, че-то, как-то да и зачем-то, вобщем получилось перешел на ехппп. Сейчас быстро исправлюсь ;). Да, кстати по поводу мпд какой ставить лучше 3-5 ? Умеет ли он как ехррр разграничивать трафик на зоны ? Блин, смутно помню почему от него отказался...

Re: разделение трафика на мир/ua-ix

Добавлено: Вт окт 06, 2009 6:58 am
star
sopov писал(а):Правильнее было бы через таблицы, да и exppp это не лучший выбор - смотрите в сторону mpd. А вообще хватит делить инет на мир и киевскую локалку с Леонтовича 9... Интернет это ведь всетаки всемирная сеть - дайте людям нормальный мир...
так всетаки откуда берутся данные из мускула или файлоф *.net

Re: разделение трафика на мир/ua-ix

Добавлено: Ср окт 07, 2009 6:48 am
star
Спасибо всем, кто отозвался :). По итогу пришлось немного перелопатить биллинг, в очередной раз разобраться как оне работает (теперь уже работал). Вобщем проблему решил так, позвал товарища, и вдвоем за 2 часа получили результат.
Пусть повторюсь но все-же,
дано:
FreeBSD 7.2(amd64), exppp,poptop+patch,abills 0.42,radius 1.1.7
Надо:
Разделить Мировой трафик и трафик UA-IX, используя IPFW , таблицами
Решение:
1.Берем файл сетей UA-IX (например отсюда http://www.colocall.net/uaix/prefixes.txt) и кладем его в /root/bin
#cd /root/bin
#fetch http://www.colocall.net/uaix/prefixes.txt
2.Обрабатываем поступивший файл скриптом uaix.net.php или любым другим...

Код: Выделить всё

<?
$file_array = file("/root/bin/prefixes.txt");
  if(!$file_array)
  {
    echo("Error opening file");
  }
  else
  {
        printf("Vsego " .count($file_array) . " podsetey UA-IX\n");
        printf("Zagruzka ");
        exec (":>/etc/uaix.sh ");
        exec ("echo \"#!/bin/sh \" >> /etc/uaix.sh \n") ;
        exec ("echo \"/sbin/ipfw table 10 flush \" >> /etc/uaix.sh \n") ;
     for($i=0; $i < count($file_array); $i++)
    {
       printf(".");
       exec ("echo \"/sbin/ipfw table 10 add  " . rtrim($file_array[$i]) . "\" >> /etc/uaix.sh \n") ;
       exec ("/bin/chmod 750 /etc/uaix.sh") ;
    }
  }
?>
#chmod 750 uaix.net.php
#php-cgi uaix.net.php
3. Добавляем таблицу
#/etc/uaix.sh
4.Меняем скрипт /usr/abills/libexec/linkupdown на скрипт с таким содержанием

Код: Выделить всё

#!/usr/bin/perl -w
# ppp
# external script for traffic shapping
#
#-------------------------------------------------------------
# /etc/ppp/ppp.linkup
#
# MYADDR:
# !bg /usr/abills/libexec/linkupdown up INTERFACE USER HISADDR
#
# /etc/ppp/ppp.linkdown
#
# MYADDR:
# !bg /usr/abills/libexec/linkupdown down INTERFACE USER HISADDR
#
#-------------------------------------------------------------
# /usr/local/etc/mpd/mpd.conf
#
# set iface up-script "/usr/abills/libexec/linkupdown mpd up"
# set iface down-script "/usr/abills/libexec/linkupdown mpd down"
#-------------------------------------------------------------
# For Linux
# 
# Add to /etc/ppp/ip-up.local 
# /usr/abills/libexec/linkupdown pppd up $1 'username' $4
#
# Add to /etc/ppp/ip-down.local 
# /usr/abills/libexec/linkupdown pppd down $1 'username' $4
#
# IPN Linux:
# /usr/local/bin/sudo /usr/abills/libexec/linkupdown ipn up eth0 %LOGIN %IP
# /usr/local/bin/sudo /usr/abills/libexec/linkupdown ipn down eth0 %LOGIN %IP
#
# IPN FreeBSD
# /usr/local/bin/sudo /usr/abills/libexec/linkupdown ipn up fxp0 %LOGIN %IP
# /usr/local/bin/sudo /usr/abills/libexec/linkupdown ipn down fxp0 %LOGIN %IP
# 
#




my $debug=0;

my $ua_table=10;

$debug=1 if ($#ARGV > -1 && $ARGV[$#ARGV] eq 'debug');

#If not anought arguments
if ( $#ARGV < 3 ) {
 print qq{Not anought argumets:
 Example:
----------------------------------------------------------------
For IPN
  \$conf{IPN_FW_START_RULE}="/usr/abills/libexec/linkupdown ipn up INTERFACE %LOGIN% %IP%";
  \$conf{IPN_FW_STOP_RULE}="/usr/abills/libexec/linkupdown ipn down INTERFACE %LOGIN% %IP%";

----------------------------------------------------------------
 /etc/ppp/ppp.linkup
 MYADDR:
   !bg /usr/abills/libexec/linkupdown up INTERFACE USER HISADDR

 /etc/ppp/ppp.linkdown
 MYADDR:
   !bg /usr/abills/libexec/linkupdown down INTERFACE USER HISADDR

----------------------------------------------------------------
 /usr/local/etc/mpd/mpd.conf
   set iface up-script "/usr/abills/libexec/linkupdown mpd up"
   set iface down-script "/usr/abills/libexec/linkupdown mpd down"
----------------------------------------------------------------
 For Linux:
 (Work only with user static IP address)
 Add to /etc/ppp/ip-up.local 
   /usr/abills/libexec/linkupdown pppd up \$1 'username' \$4

 Add to /etc/ppp/ip-down.local 
   /usr/abills/libexec/linkupdown pppd down \$1 'username' \$4
 
 For mikrotik (use it as acct external cmd /usr/abills/libexec/acct_ext):
 
  /usr/abills/libexec/linkupdown mikrotik up INTERFACE USER HISADD NAS_HOST=192.168.1.1 NAS_ADMIN=admin [SSH_CMD=.., PROTO=pptp,pppoe, debug]
  /usr/abills/libexec/linkupdown mikrotik down INTERFACE USER HISADD NAS_HOST=192.168.1.1 NAS_ADMIN=admin [SSH_CMD=.., PROTO=pptp,pppoe, debug]

DEBUG: $debug
};
exit 0;
}


use vars  qw(%RAD %conf $db @START_FW);
use strict;

use FindBin '$Bin';
require $Bin . '/config.pl';
#use lib '../', "../Abills/$conf{dbtype}";
unshift(@INC, $Bin . '/../', $Bin ."/../Abills/$conf{dbtype}");
require Abills::Base;
Abills::Base->import();
my $begin_time = check_time();

require Abills::SQL;
my $sql = Abills::SQL->connect($conf{dbtype}, "$conf{dbhost}", $conf{dbname}, $conf{dbuser}, $conf{dbpasswd});
my $db = $sql->{db};
my $OS = '';

my $argv = parse_arguments(\@ARGV);

if  ($argv->{OS}){
  $OS=$argv->{OS};
}


require Billing;
Billing->import();
my $Billing = Billing->new($db, \%conf);

my $CLIENT_IP = 'any';
my $fw_step = 1000;

my $IPFW='/sbin/ipfw';
#my @START_FW = (3000, 2000, 1000);

# Arguments
my ($ACTION, $INTERFACE, $USER, $HISADDR, $inum);

#MPD
if ($ARGV[0] eq 'mpd') {
  $ACTION   = $ARGV[1];
  $INTERFACE= $ARGV[2];
  $USER     = $ARGV[6];
  $HISADDR  = $ARGV[5];
  $inum     = $INTERFACE;
  $inum     =~ s/ng//;
}
#OpenVPN
elsif ($ARGV[0] eq 'openvpn') {
  $ACTION    = $ARGV[1];
  $INTERFACE = $ARGV[2];
  $USER      = $ARGV[6];
  $HISADDR   = $ARGV[5];
  $inum      = (! ($INTERFACE =~ s/tap//)) ? 100+8 : $INTERFACE+100;
} 
elsif ($ARGV[0] eq 'ipn') {
  $ACTION    = $ARGV[1];
  $INTERFACE = $ARGV[2];
  $USER      = $ARGV[3];
  $HISADDR   = $ARGV[4];
  $CLIENT_IP = $HISADDR;	
	my ($n1, $n2, $n3, $n4) = split(/\./, $HISADDR, 4);
  $inum  = $argv->{PORT} || $n4;

  if ($INTERFACE eq 'getif') {
    $INTERFACE = `/sbin/route -n get $HISADDR | /usr/bin/grep interface: | /usr/bin/awk '{print \$2}'`;
   }

  if ($INTERFACE =~ /eth/) {
  	$OS = 'Linux';
   }
} elsif ($ARGV[0] eq 'pppd' || $ARGV[0] eq 'mikrotik') {
  $ACTION   = $ARGV[1];
  $INTERFACE= $ARGV[2];
  $USER     = $ARGV[3];
  $HISADDR  = $ARGV[4];
  $inum     = $INTERFACE;
  if(! ($inum =~ s/ppp//)) {
  	$inum = 0;
   }
  $OS = 'Linux';

} else {
# FreeBSD PPP
  $ACTION    = $ARGV[0];
  $INTERFACE = $ARGV[1];
  $USER      = $ARGV[2];
  $HISADDR   = $ARGV[3];
  $inum      = $INTERFACE;
  $inum      =~ s/tun//;
} 


$INTERFACE=~s/\n//;
my $via_if_in  = ($INTERFACE ne '-') ? "via $INTERFACE in" : '';
my $via_if_out = ($INTERFACE ne '-') ? "via $INTERFACE out" : '';

require Admins;
Admins->import();
require Dv;
Dv->import();


my $admin = Admins->new($db, \%conf);
$admin->info($conf{SYSTEM_ADMIN_ID}, { IP => '127.0.0.1' });
my $Dv = Dv->new($db, $admin, \%conf); 

my %LIST_PARAMS = ();
my @FW_ACTIONS  = ();


# Flush rules
my($fw_num, $pipe_num, $fw_nums, $pipe_nums);

my $user = undef;
  
if ($ARGV[0] eq 'ipn') {
	if ($conf{IPN_FW_RULE_UID}) {
		$user = $Dv->info(0, { LOGIN => $USER });
		$inum = $user->{UID};
	}
	$conf{IPN_FW_FIRST_RULE}=20000 if (! $conf{IPN_FW_FIRST_RULE});
    $START_FW[0]=$START_FW[0]+$conf{IPN_FW_FIRST_RULE};
    $START_FW[1]=$START_FW[1]+$conf{IPN_FW_FIRST_RULE};
    $START_FW[2]=$START_FW[2]+$conf{IPN_FW_FIRST_RULE};
}

foreach my $num (@START_FW) {
    $fw_num     = $num + $inum * 2;
    $pipe_num   = $num + $inum * 2;
    $fw_nums   .= ' ' . ($fw_num)   .' '. ($fw_num +1);
    $pipe_nums .= ' ' . ($pipe_num) .' '. ($pipe_num+1);
}

if ($ARGV[0] eq 'pppd') {
	#push @FW_ACTIONS, "/sbin/tc qdisk del dev $INTERFACE";
	$LIST_PARAMS{IP}=$HISADDR;
} else {
	if ($OS eq 'Linux') {
	} else {
    	push @FW_ACTIONS, "$IPFW -f delete $fw_nums";
	    #push @FW_ACTIONS, "$IPFW -f pipe delete $pipe_nums";
	}
	$LIST_PARAMS{LOGIN} = "$USER";
}

# Up fw shaper rules
if ($ACTION eq 'up' || $OS eq 'Linux') {
  my %speeds = ();
  my %nets   = ();
  my %expr   = ();
  
  if (! defined($user)) {
    $user = $Dv->info(0, { %LIST_PARAMS });
  }

  if(defined($Dv->{errno})) {
     print "Error: User not exist ([$Dv->{errno}] $Dv->{errstr})\n";
     exit 1;
  } elsif ($Dv->{TOTAL} < 1) {
    print "$USER - Not exist\n";
    exit 1;
  }
 
  #JOIN Service
  $conf{JOIN_SERVICE_FW_FIRST_RULE} = 40000 if (! $conf{JOIN_SERVICE_FW_FIRST_RULE});

  if ($user->{JOIN_SERVICE}) {
 	  if ($user->{JOIN_SERVICE} > 1) {
  	  $user = $Dv->info($user->{JOIN_SERVICE});
      }   

      $user->{JOIN_SERVICE}=$user->{UID}	
  }

  if ($user->{SPEED} > 0) {
    $speeds{0}{IN} = int($user->{SPEED});
    $speeds{0}{OUT}= int($user->{SPEED});
  } else {

    ($user->{TIME_INTERVALS},
     $user->{INTERVAL_TIME_TARIF}, 
     $user->{INTERVAL_TRAF_TARIF}) = $Billing->time_intervals($user->{TP_ID});

    my ($remaining_time, $ret_attr) = $Billing->remaining_time($user->{DEPOSIT}, {
    	    TIME_INTERVALS      => $user->{TIME_INTERVALS},
          INTERVAL_TIME_TARIF => $user->{INTERVAL_TIME_TARIF},
          INTERVAL_TRAF_TARIF => $user->{INTERVAL_TRAF_TARIF},
          SESSION_START       => $user->{SESSION_START},
          DAY_BEGIN           => $user->{DAY_BEGIN},
          DAY_OF_WEEK         => $user->{DAY_OF_WEEK},
          DAY_OF_YEAR         => $user->{DAY_OF_YEAR},
          REDUCTION           => $user->{REDUCTION},
          POSTPAID            => 1,
          GET_INTERVAL        => 1,
          debug               => ($debug > 0) ? 1 : undef
         });

#    print "RT: $remaining_time\n"  if ($debug == 1);
    my %TT_IDS = %$ret_attr;


	if (keys %TT_IDS > 0) {
    	
    	require Tariffs;
     	Tariffs->import();
     	my $tariffs = Tariffs->new($db, \%conf, $admin);

		#Get intervals
		while(my($k, $v)=each( %TT_IDS)) {
        	print "$k, $v\n" if ($debug > 0);
	        next if ($k ne 'FIRST_INTERVAL');
			$user->{TI_ID}=$v;
 	      	my $list = $tariffs->tt_list({ TI_ID => $v });
 	      	foreach my $line (@$list)  {
 	    	  $speeds{$line->[0]}{IN}="$line->[4]";
 	    	  $speeds{$line->[0]}{OUT}="$line->[5]";
 	    	  $nets{$line->[0]}="$line->[7]";
 	    	  $expr{$line->[0]}="$line->[8]" if (length($line->[8]) > 5);
 	    	  #print "$line->[0] $line->[4]\n";
 	      	}
      	}
 	}
}

# speed apply
my $fw_num_in    =0;
my $fw_num_out   =0;
my $pipe_num_in  =0;
my $pipe_num_out =0;
  
  
print "Expresion:================================\n" if ($debug > 0);
my $RESULT = $Billing->expression($Dv->{UID}, \%expr, { START_PERIOD => $Dv->{ACCOUNT_ACTIVATE}, 
  	                                                      debug        => $debug } );
print "\nEND: =====================================\n" if ($debug > 0);

if (! $RESULT->{SPEED}) {
    $speeds{0}{IN}=$RESULT->{SPEED_IN} if($RESULT->{SPEED_IN});
    $speeds{0}{OUT}=$RESULT->{SPEED_OUT} if($RESULT->{SPEED_OUT});
} else {
  	$speeds{0}{IN}=$RESULT->{SPEED};
  	$speeds{0}{OUT}=$RESULT->{SPEED};
}

if ($ARGV[0] eq 'mikrotik') {
    mikrotik_ext({ SPEEDS => \%speeds,
    	             NETS   => \%nets });
    	         
  	exit;
}
  
  #Make speed rules
foreach my $traf_type (sort keys %speeds) {
	my $speed = $speeds{$traf_type};
	if (! $START_FW[$traf_type]) {
		$START_FW[$traf_type]=$START_FW[0]+$traf_type*$fw_step;
	}
	$fw_num_in    = $START_FW[$traf_type] + $inum * 2;
	$fw_num_out   = $START_FW[$traf_type] + $inum * 2 + 1;
	if ($user->{JOIN_SERVICE}) {
		$pipe_num_in = $conf{JOIN_SERVICE_FW_FIRST_RULE} + $user->{JOIN_SERVICE} * 2 + $traf_type * $fw_step;
		$pipe_num_out = $conf{JOIN_SERVICE_FW_FIRST_RULE} + $user->{JOIN_SERVICE} * 2 + 1 + $traf_type * $fw_step ;
	} else {
		$pipe_num_in  = $START_FW[$traf_type] + $inum * 2 ;
		$pipe_num_out = $START_FW[$traf_type] + $inum * 2 + 1;
	}
	my $speed_in  = (defined($speed->{IN}))  ? $speed->{IN}  : 0;
	my $speed_out = (defined($speed->{OUT})) ? $speed->{OUT} : 0;
	my @nets_arr = ();
	if ($nets{$traf_type}) {
		$nets{$traf_type} =~ s/[\r]?\n//g;
		$nets{$traf_type} =~ s/;/,/g;
		@nets_arr = split(/;|,/, $nets{$traf_type});
	}
	@nets_arr = ('0.0.0.0/0') if ($#nets_arr < 0);
	#Mikrotik shaper
    if ($ARGV[0] eq 'mikrotik' ) {
    	mikrotik_ext({ 
    		  SPEED_IN  => $speed_in,
    		  SPEED_OUT => $speed_out,
    		  NETS_ID   => undef,
    		  NETS      => \@nets_arr 
    		 });
    } elsif ($OS eq 'Linux') {
    	#Linux shaper
		my $tc = "/sbin/tc";
		my $flowid = $speed_in > 0 ? sprintf("%x",$fw_num_out) : '';
		my $drop = $speed_out > 0 ? "police rate $speed_out"."Kibit burst 12k drop" : '';
		push @FW_ACTIONS, "$tc filter del dev $INTERFACE protocol ip parent 1: prio $fw_num_out &>/dev/null";
		push @FW_ACTIONS, "$tc filter del dev $INTERFACE protocol ip parent ffff: prio $fw_num_in &>/dev/null";
		if ($flowid) {
        	push @FW_ACTIONS, "$tc class del dev $INTERFACE parent 1: classid 1:$flowid &>/dev/null";
			if ($ACTION eq 'up') {
				push @FW_ACTIONS, "$tc class add dev $INTERFACE parent 1: classid 1:$flowid htb rate $speed_in"."Kibit";
			}
		}
		if ($ACTION eq 'up') {
			foreach my $ip_full (@nets_arr) {
				if ($ip_full =~ /([!]{0,1})(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/{0,1}(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\d{1,2}):{0,1}(\S{0,200})/ ) {
					push @FW_ACTIONS, "$tc filter add dev $INTERFACE protocol ip parent 1: prio $fw_num_out u32 match ip src $2/$3 match ip dst $CLIENT_IP flowid 1:$flowid";
					push @FW_ACTIONS, "$tc filter add dev $INTERFACE protocol ip parent ffff: prio $fw_num_in u32 match ip src $CLIENT_IP match ip dst $2/$3 $drop flowid 1:";
				}
			}
		}
	} else {
    #FreeBSD ipfw pipe shaper
		if ($speed_in > 0) {
			# Speed IN limit
			if ($traf_type == 0) {
				# World in
				push @FW_ACTIONS, "$IPFW add $fw_num_in pipe $pipe_num_in ip from $CLIENT_IP to any $via_if_in";
			} else {
				# UA_IX in
				push @FW_ACTIONS, "$IPFW add $fw_num_in pipe $pipe_num_in ip from $CLIENT_IP to table\\($ua_table\\) $via_if_in";
			}
			push @FW_ACTIONS, "$IPFW pipe $pipe_num_in config bw ". $speed_in ."Kbit/s queue ". (( $speed_in / 10 > 1000 ) ? 1000 : int( $speed_in / 10 )) ."Kbytes mask dst-ip 0x00000000";
		} else {
			# Speed UNlimited
			if ($traf_type != 0) {
				push @FW_ACTIONS, "$IPFW add $fw_num_in allow ip from $CLIENT_IP to table\\($ua_table\\) $via_if_in";
			} else {
				push @FW_ACTIONS, "$IPFW add $fw_num_in allow ip from $CLIENT_IP to any $via_if_in";
			}
		}
		if ($speed_out > 0) {
			if ($traf_type == 0) {
				# World out
				push @FW_ACTIONS, "$IPFW add $fw_num_out pipe $pipe_num_out ip from any to $CLIENT_IP $via_if_out";
			} else {
				# UA-IX out
				push @FW_ACTIONS, "$IPFW add $fw_num_out pipe $pipe_num_out ip from table\\($ua_table\\) to $CLIENT_IP $via_if_out";
			}
			push @FW_ACTIONS, "$IPFW pipe $pipe_num_out config bw ". $speed_out ."Kbit/s queue ". (( $speed_in / 10 > 1000) ? 1000 : int( $speed_in / 10 ) ) ."Kbytes";
		} else {
			# Speed UNlimited
			if ($traf_type != 0) {
				push @FW_ACTIONS, "$IPFW add $fw_num_out allow ip from table\\($ua_table\\) to $CLIENT_IP $via_if_out";
			} else {
			    push @FW_ACTIONS, "$IPFW add $fw_num_out allow ip from any to $CLIENT_IP $via_if_out";
			}
		}
		}
	}
}

#make firewall actions
foreach my $line (@FW_ACTIONS) {
    if ($debug == 1) {
	print "$line\n";
    } else {
	system("$line");
    }
}



#**********************************************************
# Manage mikrotik bandwidth
# 3 type of actions
#  up
#  down 
#  check
#**********************************************************
sub mikrotik {
	my ($attr)=@_;

  
  
my $cmd   = '';
my $proto = 'pptp';
my $nets  = '';
my $nas_host  = '';
my $nas_admin = '';
my $SSH       = '/usr/bin/ssh';


foreach my $id (keys %{ $attr->{SPEEDS} }) {  
  my $interface = "<$proto-$USER>";
  my $name = "ads-$proto-$USER";
  my $speed_in  = $attr->{SPEEDS}->{$id}->{IN};
  my $speed_out = $attr->{SPEEDS}->{$id}->{OUT};
  $cmd = '';
  
  if ($id == 0) {
    $nets = '0.0.0.0/0';
   }
  else {
    $nets =  $attr->{NETS}->[0];
   }

  if ($nets ne '' || $id == 0) {
    if ($ACTION eq 'up') {
      $cmd = "/queue tree add name name=\"$name\" dst-address=0.0.0.0/0 interface=$interface
        parent=none direction=both priority=8 queue=default-small/default-small
        limit-at=$speed_in/$speed_out max-limit=$speed_in/$speed_out
        total-queue=default-small;";
     }
    elsif($ACTION eq 'down') {
      $cmd = "/queue tree add name remove [ find name=$name ];";
     }
   }

 }


  my $result = `$SSH $nas_admin\@$nas_host "$cmd"`;
}

#**********************************************************
# Manage mikrotik bandwidth
# 3 type of actions
#  up
#  down 
#  check
#**********************************************************
sub mikrotik_ext {
	my ($attr)=@_;


	my $speeds    = $attr->{SPEEDS};
	my $nets      = $attr->{NETS};

  my $proto     = $argv->{PROTO} || 'pptp';
  my $nas_host  = $argv->{NAS_HOST} || '';
  my $nas_admin = $argv->{NAS_ADMIN}|| 'admin';
  my $SSH       = $argv->{SSH_CMD}  || '/usr/bin/ssh';


  my $cmds = "$SSH $nas_admin\@$nas_host '/ppp active print where name=$USER'";
  open(CMD, "$cmds |") || die "Can't open '$cmds' $!\n";
    my @check_int = <CMD>;   
  close(CMD);

  my $protoup = (grep /pppoe/, @check_int) ? "pppoe" : "pptp";
  $INTERFACE="<$protoup-$USER>";


	my @commands  = ();

  $INTERFACE="<$proto-$USER>";

  if($ACTION eq 'down') {

    foreach my $traf_type (sort keys %$speeds) {
        
        my @nets_arr = ();
        if ($nets->{$traf_type}) {
            $nets->{$traf_type} =~ s/[\r]?\n//g;
            $nets->{$traf_type} =~ s/;/,/g;
            @nets_arr = split(/;|,/, $nets->{$traf_type});
        }

        my $address_list_name = "TT_$user->{TP_ID}_".$traf_type."_".$USER;
        my $mark_name=$address_list_name. "_mark"; 
        my $mark_name_in=$address_list_name. "_mark_in";
        my $mark_name_out=$address_list_name. "_mark_out";

        push  @commands,  "/ip firewall address-list remove [ find list=$address_list_name ]; ";
        push  @commands,  "/ip firewall mangle remove [ find comment=$mark_name_in ]; ";
        push  @commands,  "/ip firewall mangle remove [ find comment=$mark_name_out ]; ";
        push  @commands,  "/queue tree remove [ find name=$mark_name_out ] ";
        push  @commands,  "/queue tree remove [ find name=$mark_name_in ] ";
        }

    } else {

    foreach my $traf_type (sort keys %$speeds) {
    my $speed = $speeds->{$traf_type};
    
    my $speed_in  = (defined($speed->{IN}))  ? $speed->{IN} * 1024 : 0;
    my $speed_out = (defined($speed->{OUT})) ? $speed->{OUT}* 1024 : 0;
   
        my @nets_arr = ();                                                                                                                                     
            if ($nets->{$traf_type}) {                                                                                                                             
            $nets->{$traf_type} =~ s/[\r]?\n//g;                                                                                                                 
            $nets->{$traf_type} =~ s/;/,/g;                                                                                                                      
            @nets_arr = split(/;|,/, $nets->{$traf_type});                                                                                                       
        }                                                                                                                                                     
    
    my $address_list_name = "TT_$user->{TP_ID}_".$traf_type."_".$USER;
    my $mark_name_in=$address_list_name. "_mark_in";
    my $mark_name_out=$address_list_name. "_mark_out";
    my $priority = 5 - $traf_type;

    if ($traf_type == 0) {
    
      push @commands, qq{ /ip firewall mangle add chain=forward out-interface=$INTERFACE action=mark-packet new-packet-mark=$mark_name_in comment=$mark_name_in passthrough=yes };
      push @commands, qq{ /ip firewall mangle add chain=forward in-interface=$INTERFACE action=mark-packet new-packet-mark=$mark_name_out comment=$mark_name_out passthrough=yes };
      push @commands, qq{ /queue tree add name=$mark_name_in parent=$INTERFACE packet-mark=$mark_name_in limit-at=$speed_in max-limit=$speed_in queue=default-small priority=8 burst-limit=0 }; 
      push @commands, qq{ /queue tree add name=$mark_name_out parent=global-out packet-mark=$mark_name_out limit-at=$speed_out max-limit=$speed_out queue=default-small priority=8 burst-limit=0 }; 
      next;
    
     }

    foreach my $address (@nets_arr) {
   	  push @commands, qq{ /ip firewall address-list add list=$address_list_name address=$address };
    }

      push @commands, qq{ /ip firewall mangle add chain=forward out-interface=$INTERFACE src-address-list=$address_list_name action=mark-packet new-packet-mark=$mark_name_in comment=$mark_name_in passthrough=yes };
      push @commands, qq{ /ip firewall mangle add chain=forward in-interface=$INTERFACE dst-address-list=$address_list_name action=mark-packet new-packet-mark=$mark_name_out comment=$mark_name_out passthrough=yes };
      push @commands, qq{ /queue tree add name=$mark_name_in parent=$INTERFACE packet-mark=$mark_name_in limit-at=$speed_in max-limit=$speed_in queue=default-small priority=8 burst-limit=0 }; 
      push @commands, qq{ /queue tree add name=$mark_name_out parent=global-out packet-mark=$mark_name_out limit-at=$speed_out max-limit=$speed_out queue=default-small priority=8 burst-limit=0 }; 

    # Second way 
    
    # /ip firewall mangle add chain=prerouting dst-address=195.222.70.250 action=mark-onnection new-connection-mark=cybernet-connection-up passthrough=yes

    # /ip firewall mangle add chain=forward connection-mark=cybernet-connection-up ction=mark-packet new-packet-mark=cybernet-packet-up passthrough=yes

    #/ip firewall mangle add chain=prerouting src-address=195.222.70.250 action=mark-connection new-connection-mark=cybernet-connection-from passthrough=yes

    #/ip firewall mangle add chain=forward connection-mark=cybernet-connection-from action=mark-packet new-packet-mark=cybernet-packet-from passthrough=yes 
    
    #/queue tree add name="queue_$traf_type" parent=global-out packet-mark=$mark_name imit-at=0 queue=default priority=$priority max-limit=$speed_out burst-limit=0 burst-threshold=0  burst-time=0s

    #/queue tree add name="queue_$traf_type" parent=global-in packet-mark=$mark_name_in limit-at=0 queue=default priority=$priority max-limit=$speed_in burst-limit=0 burst-threshold=0s burst-time=0s 

  }
}
#else {
#    #push  @commands,  "/queue tree add name remove [ find1 name=$INTERFACE ];";
#    push  @commands,  "/queue simple remove \\\"". $INTERFACE.'_IN'. "\\\"";
#    push  @commands,  "/queue simple remove \\\"". $INTERFACE.'_OUT'. "\\\"";
#    push  @commands,  "/ip firewall address-list remove [ find list=$address_list_name ]";
#    push  @commands,  "/ip firewall mangle remove [ find address-list=$address_list_name ]";
#   push  @commands,  "/queue tree remove $mark_name";
#}



#Make ssh command	
	my $result = '';
    $result .= `echo "===> Initialising remote commands executing:" >> /var/log/shaper`;
	foreach my $cmd (@commands)  {
		print "$cmd\n" if ($debug > 0);
        $result .= `$SSH $nas_admin\@$nas_host "$cmd"; echo "$cmd" >> /var/log/shaper`;
	 }

  print $result;

}


#*****************************************************
# Parse fw params
#*****************************************************
sub parse_fw {
  my ($part) = @_;
  my $result = '';
  my %params = ();

  $part =~ s/"|//g;
  if ($part =~ / (\d+)/) {
    $params{item} = $1;
   }

  while($part =~ / ([a-zA-Z\-]+)=([a-zA-Z\-\.0-9\/<>_]+)/g) {
    my $key = $1;
    my $val = $2;
    $result .= "$key // $val\n";
    $params{"$key"}=$val;
   }

  print "\n---\n". $result if ($debug > 0);

  return \%params;
}
5. в биллинге в тарифных планах заводим два класса трафика 0:Global список подсетей 0.0.0.0/0 и 1:Extended наш (UA-IX), собственно список сетей указывать тут уже не надо. Биллинг все равно уже не будет их брать отсюда.
6. Сговорим спасибо ;)

Re: разделение трафика на мир/ua-ix

Добавлено: Ср окт 07, 2009 7:37 am
ran
4.Меняем скрипт /usr/abills/libexec/linkupdown на скрипт с таким содержанием
всё это может и было бы интересно... если бы было действительно интегрировано с линкапдаун... я имею ввиду раздельный шейпинг по классам трафика (подсетям, портам, временнЫм интервалам)... а так это поделка индивидуального пользования

Re: разделение трафика на мир/ua-ix

Добавлено: Ср окт 07, 2009 7:54 am
star
ran писал(а):
4.Меняем скрипт /usr/abills/libexec/linkupdown на скрипт с таким содержанием
всё это может и было бы интересно... если бы было действительно интегрировано с линкапдаун... я имею ввиду раздельный шейпинг по классам трафика (подсетям, портам, временнЫм интервалам)... а так это поделка индивидуального пользования
Собственно не понял что вас не устраивает ??? Читаем ВЫШЕ - ДАНО и ЗАДАЧА ! Что собственно характеризует поставленную задачу. Этот скрипт с ней справляется.
Собственно ликндаун отрабатывает нормально, трафик/деньги считает, че еще надо ???

Re: разделение трафика на мир/ua-ix

Добавлено: Ср окт 07, 2009 8:14 am
ran
Собственно не понял что вас не устраивает ???
потеря возможностей изначально реализованных в линкапдаун
ran писал(а):я имею ввиду раздельный шейпинг по классам трафика (подсетям, портам, временнЫм интервалам)
ran писал(а):всё это может и было бы интересно... если бы было действительно интегрировано с линкапдаун

Re: разделение трафика на мир/ua-ix

Добавлено: Ср окт 07, 2009 9:38 am
star
ran писал(а):
Собственно не понял что вас не устраивает ???
потеря возможностей изначально реализованных в линкапдаун
ran писал(а):я имею ввиду раздельный шейпинг по классам трафика (подсетям, портам, временнЫм интервалам)
ran писал(а):всё это может и было бы интересно... если бы было действительно интегрировано с линкапдаун
Вернемся к тому, что никаких возможностей данный апдаун не потерял! т.к. при доабавления блока сетей юаикса он не работал вообще! Если это и есть тот самы функционал, то извините меня он не устраивает ;)...
Если взглянуть на первоначальный скрипт линкапдаун то этот от него не особо отличается, просто подправлены правила фаервола для работы с таблицей. Если Вы внимательно изучите исходный linkupdown, то там как и в этом скрипте делится всего на два класса Global и Остальные! А создавать на каждого пользователя правило содержашее 1600 подсетей это глупо. В исходном linkupdown были потуги реализовать таблицы, но как говорится не работало ! Зато теперь - работает;)
Вобщем если Вам не нравится - не пользуйтесь. Я выложил данную наработку для тех, кто хочет рализовать поставленную выше задачу.

Re: разделение трафика на мир/ua-ix

Добавлено: Сб окт 17, 2009 6:18 pm
Ck-NoSFeRaTU
У мну тоже типа этого решение было одно время(нужна была поддержка ng_nat и queue, причём с нарезкой по зонам и каналам, т.е. чтобы можно было каждый тп делить на зоны по диапазонам назначения и эти зоны маршрутизировать в определенный канал и опционально трафик загонять в очереди для этого канала - для равномерного разделения полосы), но потом интегрировал полностью с биллингом, ибо гораздо удобнее всё это задавать в настройках биллинга, чем каждый раз редактировать пухнущий linkupdown.

Re: разделение трафика на мир/ua-ix

Добавлено: Вт окт 20, 2009 1:52 pm
~AsmodeuS~
в 0.5 уже все давно есть

Re: разделение трафика на мир/ua-ix

Добавлено: Ср окт 21, 2009 9:13 pm
Ck-NoSFeRaTU
~AsmodeuS~ писал(а):в 0.5 уже все давно есть
Эм... это наверное про сабж, а не про мой пост. Ибо никакого ng_nat`а и ipfw queue я ни в 0.5, ни в какой-либо другой версии абилса не видел ^_^ Да и говорил я исключительно о некрасивости и непрактичности решения автора топика.

Re: разделение трафика на мир/ua-ix

Добавлено: Чт окт 22, 2009 7:23 am
~AsmodeuS~
я говорил именно про нарезку нат єто отдельній разговор и у некоторых провайдеров сугубо индивидуальный