Скрипт не на BeanShell, а на Perl-е.
  Код:
#!/usr/bin/perl
use POSIX;
use IO::Socket;
use IO::Select;
use Socket;
use Fcntl;
use Tie::RefHash;
$debug = 1;
$port = 4445;
$ipfw = "/sbin/ipfw";
$rule_start = 35000;
#$pipe_start = 800;
$set = 10;
# База данных правил клиентов
%CLRULE = ();
%CLRULE_ID = ();
# База данных используемых номеров правил
%USERULEN = ();
%CLUSERULEN = ();
# База данных используемых номеров труб
%USEPIPEN = ();
%CLUSEPIPEN = ();
# Начать с пустыми буферами
%inbuffer   = ();
%outbuffer   = ();
%ready      = ();
tie %ready, 'Tie::RefHash';
# Прослушивать порт
$server = IO::Socket::INET->new( LocalPort => $port, Listen => 10 )
   or die "Can`t make server socket: $@\n";
nonblock( $server );
$SIG{INT} = sub { $server->close(); exit( 0 ); };
$select = IO::Select->new( $server );
$pid = getpid();
open(FILE, ">/var/run/manad.pid");
print FILE $pid;
close(FILE);
# Устанавливаем новый root каталог для процесса
# chroot( $homedir ) or die "Couldn`t chroot to $homedir: $!\n";
# Главный цикл: проверка чтения/принятия, проверка записи,
# проверка готовности к работе
while( 1 )
{
   my $client;
   my $rv;
   my $data;
   # Проверить наличие новой информации на имеющихся подключениях
   # Есть ли что-нибудь для чтения или подтверждения?   
   foreach $client ( $select->can_read( 1 ) )
   {
      if ( $client == $server )
      {
         # Принять новое подключение
         $client = $server->accept();
         $select->add( $client );
         nonblock( $client );
      }      
      else
      {
         # Прочитать данные
         $data = '';
         $rv = $client->recv( $data, POSIX::BUFSIZ, 0 );
         unless( defined( $rv ) && length $data )
         {
            # Это должен быть конец файла, поэтому закрываем клиента
            delete $inbuffer{$client};
            delete $outbuffer{$client};
            delete $ready{$client};
            $select->remove( $client );
            close $client;
            next;
         }
         $inbuffer{$client} .= $data;
         # Проверить, говорят ли данные в буфере или только что прочитанные
         # данные о наличии полного запроса, ожидающего выполнения. Если да -
         # заполнить $ready{$client} запросами, ожидающими обработки.
         while( $inbuffer{$client} =~ s/(.*\n)// ) { push( @{$ready{$client}}, $1 ) }
      }
   }
   
   # Есть ли полные запросы для обработки?
   foreach $client ( keys %ready ) { handle( $client ); }
   # Сбрасываем буферы?
   foreach $client ( $select->can_write( 1 ) )
   {
      # Пропустить этого слиента, если нам нечего сказать
      next unless $outbuffer{$client};
                block( $client );
      $rv = $client->send( $outbuffer{$client}, 0 );
      nonblock( $client );
      unless( defined $rv )
      {
         # Пожаловаться, но следовать дальше
         warn "I was told I could write? but I can`t.\n";
         next;
      }
      if ( $rv == length $outbuffer{$client} || $! == POSIX::EWOULDBLOCK )
      {
         substr( $outbuffer{$client}, 0, $rv ) = '';
         delete $outbuffer{$client} unless length $outbuffer{$client};
      }
      else
      {
         # Не удалось записать все данные и не из-за блокировки.
         # Очистить буферы и следовать дальше.
         delete $inbuffer{$client};
         delete $outbuffer{$client};
         delete $ready{$client};
         $select->remove($client);
         close($client);
         next;
      }
   }
}
# handle( $socket ) обрабатывает все необработанные запросы
# для клиента $client
sub handle
{
   # Запрос находится в $ready{$client}
   # Отправить вывод в $outbuffer{$client}
   my $client = shift;
   my $request;
   foreach $request ( @{$ready{$client}} )
   {
      print "\nrequest=".$request if ( $debug == 1 );
      if ( $request =~ /^testRID/ )
      {
         my $open_client = "";
         foreach my $kod ( keys %CLRULE )
            { $open_client .= $open_client eq "" ? $kod : " ".$kod;
            ($CLRULE_ID{$kod} ne "")?$open_client.="-".$CLRULE_ID{$kod}:"";
            }
         $outbuffer{$client} .= $open_client."\n";
      }
      elsif ( $request =~ /^test/ )
      {
         my $open_client = "";
         foreach my $kod ( keys %CLRULE )
            { $open_client .= $open_client eq "" ? $kod : " ".$kod;}
         $outbuffer{$client} .= $open_client."\n";
      }
      elsif ( $request =~ /^add\t([0-9]+)\t(.*)/ )
      {
         my ($skip,$rid)=split /RULE/,$2;
         print "\n=rule".$rid."\n" if ( $debug == 1 );
         my ($kod, $rule) = ($1, $2);
         &delete_rule( $kod ) if ( exists $CLRULE{$kod} );
         &add_rule( $kod, $rule,$rid ) if ( !exists $CLRULE{$kod} );
      }
      elsif ( $request =~ /^remove\t([0-9]+)\t(.*)/ )
      {
         &delete_rule( $1,$2 ) if ( exists $CLRULE{$1} );
      }
   }
   delete $ready{$client};
}
# nonblock( $socket ) переводит сокет в неблокирующий режим
sub nonblock
{
   my $socket = shift;
   my $flags;
   $flags = fcntl( $socket, F_GETFL, 0 )
      or die "Can`t get flags for socket: $!\n";
   fcntl( $socket, F_SETFL, $flags | O_NONBLOCK )
      or die "Can`t make socket nonblocking: $!\n";
}
sub block
{
   my $socket = shift;
   my $flags;
   $flags = fcntl( $socket, F_GETFL, 0 )
      or die "Can`t get flags for socket: $!\n";
   fcntl( $socket, F_SETFL, $flags ^ O_NONBLOCK )
      or die "Can`t make socket nonblocking: $!\n";
}
sub add_rule
{
   my $kod = $_[0];
   my $rule = $_[1];
   my $rid = $_[2];
   my %N = ();
   my %P = ();
   $CLRULE{$kod} = $rule;
   $CLRULE_ID{$kod} = $rid;
   while ( $rule =~ /\{N([AB0-9]+)\}/ )
   {
      my $n = $1;
      my $i = $rule_start - 1;
      my $j = 0;
      while( 1 )
      {
         while( 1 )
         {
            $i++;
            last if ( !exists $USERULEN{$i} );
         }
         $j++;
         last if ( $j == $n );
         last if ( $n == 0 );
      }
      $USERULEN{$i} = $kod;
      $N{$n} = $i;
      $rule =~ s/\{N$n\}/$N{$n}/g;
   }
#   while ( $rule =~ /\{P([AB0-9]+)\}/ )
#   {
#      my $p = $1;
#      my $i = $pipe_start - 1;
#      my $j = 0;
#      while( 1 )
#      {
#         while( 1 )
#         {
#            $i++;
#            last if ( !exists $USEPIPEN{$i} );
#         }
#         $j++;
#         last if ( $j == $p );
#         last if ( $p == 0 );
#      }
#      $USEPIPEN{$i} = $kod;
#      $P{$p} = $i;
#      $rule =~ s/\{P$p\}/$P{$p}/g;
#   }
   foreach my $i ( keys %N ) { $CLUSERULEN{$kod} .= exists $CLUSERULEN{$kod} && $CLUSERULEN{$kod} ne "" ? " ".$N{$i} : $N{$i}; }
#   foreach my $i ( keys %P ) { $CLUSEPIPEN{$kod} .= exists $CLUSEPIPEN{$kod} && $CLUSEPIPEN{$kod} ne "" ? " ".$P{$i} : $P{$i}; }
 #  $rule =~ s/\|pipe/; \/sbin\/ipfw -q pipe /g;
   $rule =~ s/\|table/; \/sbin\/ipfw -q table /g;
   $rule =~ s/\|add ([0-9]+)/; \/sbin\/ipfw -q add $1 set $set /g;
#        $rule =~ s/^pipe/\/sbin\/ipfw -q pipe /g;
        $rule =~ s/^table/\/sbin\/ipfw -q table /g;       
   $rule =~ s/^add ([0-9]+)/\/sbin\/ipfw -q add $1 set $set /g;
   $rule =~ s/\|/;/g;
#   print "$ipfw -q $rule\n" if ( $debug == 1 );
#   $err = `$ipfw -q $rule`;
   print "$rule\n" if ( $debug == 1 );
   $err = `$rule`;
}
sub delete_rule
{
   my $kod = $_[0];
   my $rule= $_[1];
   if ( exists $CLRULE{$kod} )
   {
      $rule =~ s/\|table/; \/sbin\/ipfw -q table /g;
          $rule =~ s/^table/\/sbin\/ipfw -q table /g;       
      $rule =~ s/\|/;/g;
#      print "$ipfw -q $rule\n" if ( $debug == 1 );
#      $err = `$ipfw -q $rule`;
      print "$rule\n" if ( $debug == 1 );
      $err = `$rule`;
      my @N = split( / /, $CLUSERULEN{$kod} );
      foreach my $i ( @N )
      {
         print "$ipfw delete $i\n" if ( $debug == 1 );
         $err = `$ipfw delete $i`;
         delete $USERULEN{$i};
      }
      my @P = split( / /, $CLUSEPIPEN{$kod} );
      foreach my $i ( @P )
      {
         print "$ipfw pipe delete $i\n" if ( $debug == 1 );
#         $err = `$ipfw pipe delete $i`;
#         delete $USEPIPEN{$i};
      }
      delete $CLUSERULEN{$kod};
#      delete $CLUSEPIPEN{$kod};
      delete $CLRULE_ID{$kod};
      delete $CLRULE{$kod};
   }
}.
 Скрипт был взят с этого форума, "переделанный под работу с табличками". Шейпер реализован другими методами, поэтому выкинут из скрипта. Такой же скрипт работает на другом шлюзе с freebsd, там проблем нет, но клиентов там на сейчас немного меньше. Этот скрипт тоже работал "как надо", проблемы начались после "перехода" какого-то количества клиентских записей, привязанных к шлюзу. Лично у меня сложилось такое ощущение, что не хватает каких-то буферов (может на прием на шлюзе, может на передачу, на сервере), - при запуске задачи "проверка шлюзов ipn" на "проблемном" шлюзе наблюдаю, что он начал обрабатывать запросы с сервера(БГ), но на каком-то этапе его "клинит"...