Появилась идея( не новая) а как бы запретить закачку , а серфинг разрешить. всякие флаги и т.д. после изучения были отметены как слишком сложные в реализации.
Решили реализовать такой алгоритм - есть тариф - например 1000 мбит на скорости 1024 Кбит/cek как прошли порог - 128 Кбит/сек и безлимит на месяц. После порога смотрим как пользователь использует канал, если за 2 минуты он занял канал больше , чем на 20% скорость падает в 2 раза, через 2 минуты смотрим снова - больше 20 % скрость еще падает. и т.д.
Описание работы: Используем FreeBSD 6.2 шейпер сделан с использованием pipe и table. В таблицу 1 передаем значения IP и BW - с помощью rfw. А на основе таблицы генеряться динамические pipe.
Для тех тарифов которые работают в режиме динамического шейпирования добавляем правило: add RULE_ID count ip from any to UIP при включении и соответственно правило для удаления.
По крону раз в 2 минуты( можно и чаще) запускаем скрипт
- #!/usr/bin/perl
use IO::File;
use strict;
sub get
{
my $ip = shift;
my $rule = `/sbin/ipfw table 1 list | grep $ip`;
my (@field) = split(/\s+/, $rule);
return $field[1] || '0';
};
sub set
{
my $ip = shift;
my $bw = shift || '0';
system sprintf '/sbin/ipfw -q table 1 delete %s', $ip;
system sprintf '/sbin/ipfw -q table 1 add %s %d', ($ip, $bw);
return 1;
};
my $fh = IO::File->new('/netup/utm5/log/dynashape.tmp') || die "Unable to open dynashape.tmp!\n\n";
while ( <$fh> )
{
my (@var) = split(/\s+/, $_);
next if ( $var[4] > 512 );
my $rule = `/sbin/ipfw show | grep count | grep $var[1]`;
next if (!$rule);
my (@field) = split(/\s+/, $rule);
next if ($field[2]==0);
system "/sbin/ipfw -q zero $field[0]";
my $bw = get($var[1]);
if ( $bw > 0 )
{
my $max = int($bw*1000/8*0.92*120);
if ( ($field[2] > ($max/5)) && ($bw/2 > 16) ) { set($var[1], $bw/2); printf STDERR "%s: %dkbps -> %dkbps\n", ($var[1], $bw, $bw/2); }
# elsif ( ($field[2] < ($max/5)) && ($bw < $var[4]) ) { set($var[1], $var[4]); printf STDERR "%s: %dkbps -> %dkbps\n", ($var[1], $bw, $var[4]); };
}
}
$fh->close();
Все сделанно только для исходящего на пользователя трафика - входящий не шейпируем.