Биллинговая система Nodeny
28 Сентября 2024, 23:32:07 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Прекращена поддержка версии Nodeny 49
 
   Начало   Помощь Поиск Войти Регистрация  
Страниц: 1 [2] 3 4 5
  Печать  
Автор Тема: Модуль получения МАС-адреса (OLD: получение МАС адреса)  (Прочитано 32149 раз)
Fredik
NoDeny
Старожил
*

Карма: 5
Offline Offline

Сообщений: 362


Просмотр профиля
« Ответ #15 : 19 Ноября 2009, 10:31:08 »

та отож. ))
Записан
Andrey Zentavr
NoDeny
Старожил
*

Карма: 29
Offline Offline

Сообщений: 301



Просмотр профиля
« Ответ #16 : 22 Ноября 2009, 05:18:12 »

Модуль готов, проходит обкат в одной из сетей г. Запорожье.
С пользовательской стороны выглядит примерно следующим образом:

..Модуль подключается в клиентскую статистику и доступен только из админки. При нажатии оператором/администратором на кнопку "Пинговать" отправляется XMLHttpRequest (тот самый Ajax) на скрипт stat.pl, который через IO::Socket цепляеться непосредственно на роутер где юзеры висят (точнее на TCP-порт, который слушает Perl-скрипт и выполняет всякий арпинг (пинг по маку)). Роутер выдаёт выхлоп, который перенаправляется в браузер через админку НоуДеная. При любом результате ответ отображается в правом div'е.

При нажатии на кнопку "Обновить" выполняется привязка текущего значения дополнительного параметра MAC-адрес к ИПу учётной записи. Причём если это поле пустое - то генериться случайный мак и выполняется привязка к случайному маку.


Работа модуля была проверена в следующих браузерах:
1) Mozilla Firefox 3.5.5
2) Opera 9.63 (новее в загашнике не нашел, уверен что проблем не будет)
3) Apple Safari 4.03
4) MS Internet Explorer 8.0.7600.16385
« Последнее редактирование: 22 Ноября 2009, 05:33:45 от Andrey Zentavr » Записан
Fredik
NoDeny
Старожил
*

Карма: 5
Offline Offline

Сообщений: 362


Просмотр профиля
« Ответ #17 : 22 Ноября 2009, 17:42:33 »

а нам когда потестить даш?
Записан
Andrey Zentavr
NoDeny
Старожил
*

Карма: 29
Offline Offline

Сообщений: 301



Просмотр профиля
« Ответ #18 : 22 Ноября 2009, 17:50:14 »

а нам когда потестить даш?
Так лень писать доки в выходные. Напишу доку по установке и выложу.
Записан
VitalVas
NoDeny
Спец
*

Карма: 60
Offline Offline

Сообщений: 991



Просмотр профиля WWW
« Ответ #19 : 22 Ноября 2009, 17:51:21 »

ждемсс....
Записан
Andrey Zentavr
NoDeny
Старожил
*

Карма: 29
Offline Offline

Сообщений: 301



Просмотр профиля
« Ответ #20 : 23 Ноября 2009, 15:46:36 »

Модуль и дока во вложении. Перед установкой смотри install.txt

О результатах работы отписываемся здесь.

Модуль тестировался на версии 50.32
Записан
Fredik
NoDeny
Старожил
*

Карма: 5
Offline Offline

Сообщений: 362


Просмотр профиля
« Ответ #21 : 23 Ноября 2009, 17:23:34 »

 /usr/local/etc/rc.d/arping_serv.sh start
Starting arping_serv
Use of uninitialized value in numeric eq (==) at /usr/local/sbin/arping_serv.pl line 98.

/usr/local/etc/rc.d/arp_refresh.sh start
Starting arp_refresh
Use of uninitialized value in numeric eq (==) at /usr/local/sbin/arp_refresh.pl line 27.


в админке
Wrong first octet 171.**.**.**
Operation Completed!


Записан
Efendy
Администратор
Спец
*****

Карма: 138
Offline Offline

Сообщений: 4787



Просмотр профиля
« Ответ #22 : 23 Ноября 2009, 21:28:25 »

это в результате ключа -w перла. Ключ заставляет перл выводить предупреждения. В данном случае это не критично, хотя для лучшего стиля лучше б было определить переменную $err
Записан
Andrey Zentavr
NoDeny
Старожил
*

Карма: 29
Offline Offline

Сообщений: 301



Просмотр профиля
« Ответ #23 : 23 Ноября 2009, 21:55:56 »

в админке
Wrong first octet 171.**.**.**
Operation Completed!
Ну дык ты скопипастил скрипты и пытаешся их под свои подсети юзать. Я ж написал в инсталле.тхт - что у меня подсети вида 10.1.подсеть.*, потому я проверяю октет чтобы он был "10". Тебе прийдёться под себя внутренности переписать.
Или просить меня сделать скрипт более универсальным. Возможно это будет немного позже, но стопудово после 29го января, когда я защитю второй диплом, который не имеет отношения к моей первой технической специальности.
Записан
Александр (AleksHr)
NoDeny
Старожил
*

Карма: 2
Offline Offline

Сообщений: 323


Просмотр профиля
« Ответ #24 : 14 Декабря 2009, 16:03:42 »

Настроил под свои подсети упешно - мак пингуется и отображается праивльно.

Но проблема - при нажатии кнопки обновить - пишет Internal Server Error!

Вроде все хорошо, в настройках скриптов поле 4 и есть поле для мака, как посмотреть подробнее где ошыбка?
« Последнее редактирование: 14 Декабря 2009, 16:52:29 от Александр (AleksHr) » Записан
Александр (AleksHr)
NoDeny
Старожил
*

Карма: 2
Offline Offline

Сообщений: 323


Просмотр профиля
« Ответ #25 : 15 Декабря 2009, 17:13:21 »

Ну кто нибудь поможет? Неужели никто не использует у себя?
Записан
Maks
NoDeny
Ветеран
*

Карма: 13
Offline Offline

Сообщений: 575


Скажи спасибо - подними карму.

https://t.me/smv https://t.me/smv_wz
Просмотр профиля Email
« Ответ #26 : 17 Декабря 2009, 12:05:35 »

Извените если возможно не в тему.
Абоненты авторизируются по PPPoE:
1) нужно чтоб скрипт делал заносил MAК клиетна в его Дополнительные данные.
Но привязку по МАК делать не нужно.
2 )Реализовать поиск маков по биллингу.
Это поможет  в вычислениях вирусовых абонов, да и другие конфликты где видно мак сетевой карты.
IP можно сменить ( если ручками писать) а вот мак, мало кто будет менять.( я не отрицаю что это возможно).
Записан

Nodeny общение
https://t.me/nodeny_chat
Andrey Zentavr
NoDeny
Старожил
*

Карма: 29
Offline Offline

Сообщений: 301



Просмотр профиля
« Ответ #27 : 19 Декабря 2009, 14:39:45 »

Настроил под свои подсети упешно - мак пингуется и отображается праивльно.

Но проблема - при нажатии кнопки обновить - пишет Internal Server Error!

Вроде все хорошо, в настройках скриптов поле 4 и есть поле для мака, как посмотреть подробнее где ошыбка?
В error.log'ах Апача.
При нажатии на кнопку "Обнеовить" происходит отправка AJAX-запроса на сервер.
Ошибка может возникать из-за того, что не выполняеться подпрограмма модуля.
Код:
# Нам пришел запрос на обновления кеша IP<->MAC
$ip = &Filtr_out($F{arpupd});
# Проверяем, ИП ли это?
$ipcheck = &ARP_checkip($ip);
if ( $ipcheck == 1 ){
# Делаем запрос на сервак
use IO::Socket;
$|=1;
$socket = IO::Socket::INET->new(PeerAddr => $ARP_config{"server"},
                                PeerPort => $ARP_config{"updport"},
                                Proto    => $ARP_config{"proto"},
                                Type     => SOCK_STREAM)
or die "Content-type: text/html\n\nCouldn't connect to ".$ARP_config{"server"}.":".$ARP_config{"pingport"}." : $@\n";
$socket->autoflush(1);
# Шлём в сокет ИП
$socket->send($ip."\n");
# Нам пришел ответ
$socket->recv($answer, 1024);
close($socket);
# Закрываем сокет
# И отправим клиенту всю эту бадягу
print "Content-type: text/html\n\n".$answer;
exit;
}else{
# Шлём клиенту
if($ipcheck == 0){
$err = "Параметр не похож на IP-адрес\n";
}else{
$err = "Не верный ".(-1 * $ipcheck)." октет IP-адреса\n";
}
$out = "Не верно указан IP-адрес ".$ip."\n".$err;
print "Content-type: text/html\n\n".$out;
exit;
}
- возможно что-то здесь изменили, или не происходит соединение со скриптом, который выполняет подстановку.
Записан
Andrey Zentavr
NoDeny
Старожил
*

Карма: 29
Offline Offline

Сообщений: 301



Просмотр профиля
« Ответ #28 : 19 Декабря 2009, 14:45:47 »

Извените если возможно не в тему.
Абоненты авторизируются по PPPoE:
1) нужно чтоб скрипт делал заносил MAК клиетна в его Дополнительные данные.
Но привязку по МАК делать не нужно.
Откуда скрипту их брать (маки)? У меня когда-то в своё время был скрипт, который три недели собирал маки клиентов, чтобы 1.5к записей не вносить ручками. Когда более-менее на 90% база заполнилась - скрипт-сборщик остановили и остальное дописывали ручками.

2 )Реализовать поиск маков по биллингу.
Это поможет  в вычислениях вирусовых абонов, да и другие конфликты где видно мак сетевой карты.
IP можно сменить ( если ручками писать) а вот мак, мало кто будет менять.( я не отрицаю что это возможно).
У меня поиск по маку ведёться следующим образом:
В админке справа вверху есть ссылка "Поиск", нажимаем на неё -> Поиск клиентов по данным в разделе -> выбираем "Сетевые параметры" -> ну и тут уже вбиваем мак.
Записан
Александр (AleksHr)
NoDeny
Старожил
*

Карма: 2
Offline Offline

Сообщений: 323


Просмотр профиля
« Ответ #29 : 19 Декабря 2009, 17:44:05 »

Цитировать
[Sat Dec 19 17:36:52 2009] [error] [client 10.46.16.211] , referer: https://10.46.16.1/stat.pl?pp=T1-435304263WZ5w!wNAfQOPUXgZNEjHiQ&a=101&id=124&a=302
[Sat Dec 19 17:36:52 2009] [error] [client 10.46.16.211] Couldn't connect to 10.46.16.1:14120 : IO::Socket::INET: connect: Connection refused, referer: https
[Sat Dec 19 17:36:52 2009] [error] [client 10.46.16.211] Premature end of script headers: stat.pl, referer: https://10.46.16.1/stat.pl?pp=T1-435304263W
[Sat Dec 19 17:36:52 2009] [error] [client 10.46.16.211] File does not exist: /usr/local/www/stats/data/error, referer: https://10.46.16.1/stat.pl?pp=T

Вот такие ошыбки в логах апача при нажатии кнопку обновить. Проблема в соединении на сколько я понял, но мак адрес же отображается правильно когда нажымать пинговать!

Sarping.pl
Цитировать
sub ARP_main{
        # так как конфижить всё это добро в конфиге биллинга нельзя, прийдёться это сделать один раз здесь.
        my %ARP_config = (
                        "server" => "10.46.16.1",
                        "pingport" => "14120",
                        "updport" => "14121",
                        "proto" => "tcp",
        );


Кусок с настройками.

В чем может быть проблемма?

arp_refresh.pl
Цитировать
#!/usr/bin/perl -w

use POSIX;
use IO::Socket;
use IO::Select;
use Fcntl;
use Tie::RefHash;
use DBI;

my %config = (
         "pid" => "/var/run/arp_refresh.pid",
         "arp" => "/usr/sbin/arp",
         "count" => 5,
         "ip"   => "10.46.16.1",
         "port"   => "14121",
         "proto"   => "tcp",
         "MySQL" => {
                "sqlfirst" => "DBI:mysql:bill;127.0.0.1",
               "sqllogin" => "***",
               "sqlpasswd" => "***",
         },
         "dopfield_id" => 4,
);


open PID, ">".$config{"pid"} or $err=$!;
if ($err==0) {
    print PID $$;
    close PID;
}


sub trim {
    my($string)=@_;
    for ($string) {
   s/^\s+//;
   s/\s+$//;
    }
    return $string;
}

# handle($socket) deals with all pending requests for $client
sub handle {
    # requests are in $ready{$client}
    # send output to $outbuffer{$client}
    my $client = shift;
    my $request;
                       
    foreach $request (@{$ready{$client}}) {
        # $request is the text of the request
      # put text of reply into $outbuffer{$client}
      $str = trim($request);
      
      # Do we have ip??
       if( $str =~ /^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.[0-9]{1,3}/) {
         $first   = $1;
         $second   = $2;
         $net   = $3;
         
         if($first eq 10 ){
            if($second eq 46){
               if($net eq 16 ||
                  $net eq 17 ||
                  $net eq 18 ||
                  $net eq 19) {
                  
                  ##################################
                  undef $dbh;
                  undef $myst;
                  # Коннектимся к Мускл
                  $dbh=DBI->connect($config{"MySQL"}{"sqlfirst"},$config{"MySQL"}{"sqllogin"},$config{"MySQL"}{"sqlpasswd"}) or print "Error $! !\n";
                  # Запрашиваем МАС
                  $query="SELECT d.field_value AS mac FROM users u, dopvalues d, (
                              SELECT u.ip AS ip, MAX(d.revision) AS rev FROM users u, dopvalues d
                                 WHERE u.id=d.parent_id AND d.dopfield_id=".$config{'dopfield_id'}." AND u.ip='".$str."'
                                 GROUP BY ip
                              ) AS tmp
                           WHERE u.id=d.parent_id
                           AND d.dopfield_id=".$config{'dopfield_id'}."
                           AND u.ip=tmp.ip
                           AND d.revision=tmp.rev
                           AND TRIM(d.field_value) != ''";
                  # Готовим запрос
                  $myst = $dbh->prepare($query);
                  # Делаем экзекуцию запросу Улыбающийся
                  $myst->execute;
                  # Выдёргиваем МАС
                  ($mac) = $myst->fetchrow;
                  # Если вдруг мака нету, генерим какой-то фэйковый
                  if($mac eq ''){
                     $mac = sprintf("%x:%x:%x:%x:%x:%x", int(rand(255)), int(rand(255)), int(rand(255)), int(rand(255)), int(rand(255)),int(rand(255)));            
                     $outbuffer{$client} .= "Generated FAKE mac!\n";
                  }
                  # Делаем привязку IP <-> MAC
                  system($config{"arp"}." -s ".$str." ".$mac);
                  $outbuffer{$client} .= $str." ".$mac."\n";
                  # Закрываем MySQL соединение            
                  $myst->finish;            
                  $dbh->disconnect;
                  #####################################      
               } else {
                  $outbuffer{$client} .= "Wrong third octet **.**.".$net.".**\n";
               }
            } else {
               $outbuffer{$client} .= "Wrong second octet **.".$second.".**.**\n";
            }
         } else {
            $outbuffer{$client} .= "Wrong first octet ".$first.".**.**.**\n";
         }         
       } else {
         print "Garbage from ".$client->peerhost().":".$client->peerport().": ".$str."\n";
       }      
      #################################################
    }
    delete $ready{$client};
}

# nonblock($socket) puts socket into nonblocking mode
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";
}

# Создаём сокет
my $server = IO::Socket::INET->new (
                LocalAddr => $config{"ip"},
                LocalPort => $config{"port"},
                Proto => $config{"proto"},
                Listen => 10,
                Reuse => 1,               
        ) or die "Can't bind : $@\n";

nonblock($server);
my $select = new IO::Select->new($server);

# begin with empty buffers
%inbuffer  = ();
%outbuffer = ();
%ready     = ();

tie %ready, 'Tie::RefHash';

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;
            #print "Client had gone Грустный\n";
            next;
         }      
         
         $inbuffer{$client} .= $data;
         
         # test whether the data in the buffer or the data we
         # just read means there is a complete request waiting
         # to be fulfilled.  If there is, set $ready{$client}
         # to the requests waiting to be fulfilled.
         while ($inbuffer{$client} =~ s/(.*\n)//) {
            push( @{$ready{$client}}, $1 );
         }                                                                                                                                                                                                
      }
    }
   
    # Any complete requests to process?
    foreach $client (keys %ready) {
      handle($client);
    }
   
    # Buffers to flush?
    foreach $client ($select->can_write(1)) {
    # Skip this client if we have nothing to say
   next unless exists $outbuffer{$client};
       
        $rv = $client->send($outbuffer{$client}, 0);
        unless (defined $rv) {
           # Whine, but move on.
           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 {
           # Couldn't write all the data, and it wasn't because
           # it would have blocked.  Shutdown and move on.
           delete $inbuffer{$client};
           delete $outbuffer{$client};
            delete $ready{$client};
           
            $select->remove($client);
            close($client);
            next;
        }
    }
   
    # Out of band data?
    foreach $client ($select->has_exception(0)) {  # arg is timeout
      # Deal with out-of-band data here, if you want to.
    }
}

exit 0;

arping_serv.pl
Цитировать
#!/usr/bin/perl -w

use POSIX;
use IO::Socket;
use IO::Select;
use Fcntl;
use Tie::RefHash;

my %config = (
         "pid" => "/var/run/arping_serv.pid",
         "arping" => "/usr/local/sbin/arping",
         "count" => 5,
         "ip"   => "10.46.16.1",
         "port"   => "14120",
         "proto"   => "tcp",
         "cards" => {
                "16" => "fxp0",
               "17" => "fxp0",
               "18" => "fxp0",
               "19" => "fxp0"
         },
);

 
sub trim {
    my($string)=@_;
    for ($string) {
   s/^\s+//;
       s/\s+$//;
    }
return $string;
}

# handle($socket) deals with all pending requests for $client
sub handle {
    # requests are in $ready{$client}
    # send output to $outbuffer{$client}
    my $client = shift;
    my $request;
                       
    foreach $request (@{$ready{$client}}) {
        # $request is the text of the request
      # put text of reply into $outbuffer{$client}
      $str = trim($request);
      
      # Do we have ip??
       if( $str =~ /^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.[0-9]{1,3}/) {
         $first   = $1;
         $second   = $2;
         $net   = $3;         
         if($first eq 10 ){
            if($second eq 46){
               if(exists($config{"cards"}{$net})) {
                  #print $new_sock "$arping -i$card2x -c$count $ip\n";            
                  foreach(`$config{"arping"} -i$config{"cards"}{$net} -c$config{"count"} $str`){
                     #print "$_\n";
                     if(/\w+ bytes from \w+:\w+:\w+:\w+:\w+:\w+ .+/){
                        ($mac) = /\w+ bytes from (\w+:\w+:\w+:\w+:\w+:\w+) .+/;
                        $outbuffer{$client} .= "$mac\n";
                     }
                  }
               } else {
                  $outbuffer{$client} .= "Wrong third octet **.**.".$net.".**\n";
               }
            } else {
               $outbuffer{$client} .= "Wrong second octet **.".$second.".**.**\n";
            }
         } else {
            $outbuffer{$client} .= "Wrong first octet ".$first.".**.**.**\n";
         }
       } else {
         print "Garbage from ".$client->peerhost().":".$client->peerport().": ".$str."\n";
       }      
      #################################################
    }
   $outbuffer{$client} .= "Operation Completed!\n";
    delete $ready{$client};
}

# nonblock($socket) puts socket into nonblocking mode
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";
}


open PID, ">".$config{"pid"} or $err=$!;
if ($err==0) {
    print PID $$;
    close PID;
}

my $server = IO::Socket::INET->new (
                LocalAddr => $config{"ip"},
                LocalPort => $config{"port"},
                Proto => $config{"proto"},
                Listen => 10,
                Reuse => 1,               
        ) or die "Can't bind : $@\n";

nonblock($server);
my $select = new IO::Select->new($server);

# begin with empty buffers
%inbuffer  = ();
%outbuffer = ();
%ready     = ();

tie %ready, 'Tie::RefHash';
     

# Arping Server main code
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;
            #print "Client had gone Грустный\n";
            next;
         }      
         
         $inbuffer{$client} .= $data;
         
         # test whether the data in the buffer or the data we
         # just read means there is a complete request waiting
         # to be fulfilled.  If there is, set $ready{$client}
         # to the requests waiting to be fulfilled.
         while ($inbuffer{$client} =~ s/(.*\n)//) {
            push( @{$ready{$client}}, $1 );
         }                                                                                                                                                                                                
      }
    }
   
    # Any complete requests to process?
    foreach $client (keys %ready) {
      handle($client);
    }
   
    # Buffers to flush?
    foreach $client ($select->can_write(1)) {
    # Skip this client if we have nothing to say
   next unless exists $outbuffer{$client};
       
        $rv = $client->send($outbuffer{$client}, 0);
        unless (defined $rv) {
           # Whine, but move on.
           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 {
           # Couldn't write all the data, and it wasn't because
           # it would have blocked.  Shutdown and move on.
           delete $inbuffer{$client};
           delete $outbuffer{$client};
            delete $ready{$client};
           
            $select->remove($client);
            close($client);
            next;
        }
    }
   
    # Out of band data?
    foreach $client ($select->has_exception(0)) {  # arg is timeout
      # Deal with out-of-band data here, if you want to.
    }
}

exit 0;
Записан
Страниц: 1 [2] 3 4 5
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.20 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!