Как стать автором
Обновить

Как быть, если твой провайдер Akado?

Время на прочтение3 мин
Количество просмотров883
Под хабракатом приведены примеры скриптов, упрощающие жизнь :)

Часть 1. Проверка получаемого адреса


В своё время у Акадо наблюдались проблемы с авторизацией pppoe.
И поскольку при загрузке системы часть демонов привязывалась к получаемому ip адресу, то нужно было как-то автоматизировать процесс загрузки системы и исключить ситуацию простоя.
Идея заключалась в том, чтоб после запуска pppd проверять полученный от провайдера адрес.
Сам скрипт представляет из себя следующее:
i=0
pppip="<my_ip>"
echo -e "waiting pppoe connection"
until [ "$i" -eq "30" ]
do
iconf=`/sbin/ifconfig tun0 | awk '/inet/ {print $2}'`
if [ "$iconf" = "$pppip" ]
then
echo -e "successful"
i="30"
break
else
i=`expr $i + 1`
echo -n "."
sleep 5
fi
done
if [ "$iconf" != "$pppip" ]
then
echo -e "pppoe not connected!\nSystem will be reboot"
reboot
fi

и добавлен в /etc/rc.d/ppp.
Если не удалось получить требуемый адрес, то отправляем машинку в ребут.
Почему не пытаемся перезапустить сам демон ppp?
К моменту проверки ещё не многое запущено, поэтому исключаем версию о том, что перезагрузка будет долгой — до момента остановки процессов, а усложнять конструкцию очень не хотелось.

Часть 2. Проверка соединения


Помимо описанной выше ситуации могут случиться проблемы с потерей соединения.

Хочу оговориться, что полёт пакетов происходит след. образом:
  • для работы локальной сети используется адрес, выдаваемый от dhcp сервера провайдера;
  • для выхода во вне используется pppoe.

Скрипт запускается по крону с периодом в 10 минут и если пинг неудачен до внутренних адресов, то пытаемся переполучить адрес от dhcp, до внешних — рестартим pppd.
#!/usr/bin/perl

use strict;
use warnings;
use threads;
use Touch;
use Net::Ping;
use Net::Ifconfig::Wrapper qw(Ifconfig);

my @check_hosts	= qw/ya.ru google.com/;
my @check_ips	= qw/172.18.1.1 172.18.1.2/;
my $int_if	= 're0';
my $ext_if	= 're1';


sub get_ips {
  my ($iface) = @_ ;
  my @ifaces = ();
  my $info = Ifconfig('list', '', '', '');

  unless ( defined($info->{$iface}) ) {
    die "Couldn't find ip address on $iface\n";
  }

  for ( sort keys %{$info->{$iface}{'inet'}} ) {
    push(@ifaces,$_);
  }

  if ( scalar(@ifaces) > 0 ) {
    return \@ifaces;
  }
  else {
    return undef;
  }
}


sub ping_state {
  my ($dst_src,$proto,$iface) = @_;

  die "Check params in sub ping_state"
    unless ( defined($dst_src) && ref($dst_src) eq 'ARRAY' );

  $proto = ''
    unless ( defined($proto) );

  my $p = Net::Ping->new($proto);

  my $int_ips = undef;
  $int_ips = get_ips($iface)
    if ( defined($iface) );
  $p->bind($int_ips->[0])
    if ( defined($int_ips) );

  my $i = 0;
  for my $sources ( @{$dst_src} ) {
    if ( $p->ping($sources,10) ) {
      $i++; last;
    }
  }

  $p->close();
  if ($i > 0) { return 1; }
  else { return 0; }
}


sub do_log {
  my ($message,$log_file) = @_;

  $log_file = '/var/log/ifaces.log'
    unless ( defined($log_file) );

  unless ( -e "$log_file" ) {
    touch($log_file) or die("Failed touch $log_file");
  }

  open(LOG,">> $log_file");
  my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  print LOG '[' . ($year+1900) .
            '-' . ( ( $mon < 10 ) ? ( '0'.$mon ) : $mon ) .
            '-' . ( ( $mday < 10 ) ? ( '0'.$mday ) : $mday ) . 
            ' ' . ( ( $hour < 10 ) ? ( '0'.$hour ) : $hour ) .
            ':' . ( ( $min < 10 ) ? ( '0'.$min ) : $min ) .
            ':' . ( ( $sec < 10 ) ? ( '0'.$sec ) : $sec )  .
            ']' . "$message\n";
  close LOG;
}

my $thr = threads->create(sub {
  unless ( ping_state(\@check_ips,'tcp',$int_if) ) {
    do_log("Check connect to LAN resources : failed");
    system("dhclient $ext_if");
  }
});

unless ( ping_state(\@check_hosts,'icmp') ) {

  do_log("Check connect to WAN resources : failed");
  opendir(RUN,'/var/run');
  for ( grep {/tun\w+\.pid/} readdir(RUN) ) {
    open(PID,'/var/run/' . "$_");
    local $/ = undef;
    my $pid = <PID>;
    close(PID);
    chop($pid);
    kill(9,$pid);
  }
  closedir(RUN);

  system("ppp -ddial akado");
}

foreach my $t ( threads->list(threads::all) ) {
  $t->join();
}


Не забываем подставить свои значения проверяемых внутренних ресурсов (см. определение массива @check_ips).
В /var/log/ifaces.log можем отслеживать проблемы.

Само собой, можно было убрать использование модуля Touch и по иному описать часть операций, но мне в момент написания хотелось именно так :)

P.S.: используется FreeBSD, Perl 5.10.
Перл 5.8 будет ругаться на использование threads->list(threads::all).
Теги:
Хабы:
Всего голосов 16: ↑12 и ↓4+8
Комментарии16

Публикации