Скрипт автоматического переключения между основным и резервным каналом

Версия для печатиОтправить другуPDF version

Есть офисный маршрутизатор на базе FreeBSD и два приходящих канала Internet.

Поставлена задача: автоматизировать переключения с основного канала на резервный в случае его падения и обратно, после возобновления работы основного канала.

В "закромах Родины" завалялся perl-скрипт, происхождение которого установить не получилось. Скорее всего был скачан "на всякий случай" из инета.

Итак, проанализировав содержимое скрипта, выполняем установку необходимого расширения Perl - Net-Ping:

# cd /usr/ports/net/p5-Net-Ping-External && make install clean && rehash

Далее правим переменные в скрипте. Листинг скрипта следующий:

#!/usr/local/bin/perl -w
use strict;
use warnings;

use Net::Ping::External (qw(ping));

# 1 - автоматический режим переключение канала
# 2 - принудительное переключение на второй канал.
my $action = 1;
my $host_gw = "192.168.213.129"; # default gateway
my $gw = "192.168.178.209"; # backup gateway
my $now = localtime time;
my $log = "/var/log/route-change.log";


if($action == 1){


my $command = `netstat -rn | grep default`;
my @b = split('\s+',$command,3);


if (ping(hostname=>$host_gw, count=>5)){
   print "host $host_gw is ok\n";
       if($b[1] ne $host_gw){
           if($b[1] eq ""){
               `route add default $host_gw`;
           }else{
               `route change default $host_gw`;
               open(LOG,">>$log");
                   print LOG "[!] $now Route change to $host_gw\n";
               close(LOG);
           }
       }
}else{
   print "host $host_gw is bad.\n";
   if($b[1] ne $gw){
     `route change default $gw`;
   open(LOG,">>$log");
       print LOG "[!] $now Route change to $gw\n";
   close(LOG);
   }
}
}


if($action == 2){


my $command = `netstat -rn | grep default`;
my @b = split('\s+',$command,3);


if($b[1] ne $gw){
   if($b[1] eq ""){
       `route add default $gw`;
   }else{
       `route change default $gw`;
       open(LOG,">>/change_route.log");
           print LOG "[!] $now Route change to $gw\n";
       close(LOG);
   }
   }
}

Разместим данный скрипт под названием route-change.pl  в каталоге /usr/local/etc. Проверим дефолт до запуска скрипта:

# netstat -rn | grep default
default            192.168.213.129     UGS       335 51206943 vlan32

Запустим скрипт:

 

# perl /usr/local/etc/route-change.pl
host 192.168.213.129 is ok

Проверяем значение маршрута по умолчанию:

 

# netstat -rn | grep default
default            192.168.213.129     UGS       346 51212415 vlan32

Проверим, выполняется ли переключение, выполнив имитацию падения канала.

 

# ipfw add 1 deny icmp from any to 192.168.213.129
00001 deny icmp from any to 192.168.213.129

# perl /usr/local/etc/route-change.pl
host 91.204.213.129 is bad.

# netstat -rn | grep default
default            192.168.178.209     UGS       521 51732384 vlan33

Все работает! Осталось только проверить, происходит ли обратное переключение на основной канал:

 

# ipfw 1 delete

# perl /usr/local/etc/route-change.pl
host 91.204.213.129 is ok

# netstat -rn | grep default
default            192.168.213.129     UGS       374 51751262 vlan32

 

Проверим, ведется ли логгирование переключений:

# cat /var/log/route-change.log
[!] Thu Oct 28 16:13:45 2010 Route change to 85.223.178.209
[!] Thu Oct 28 16:16:41 2010 Route change to 91.204.213.129

Все гуд... Последний штрих - добавим запуск скрипта в cron с ежеминутным запуском:

# echo '# Route check and change' >> /etc/crontab

# echo '* * * * *       root    /usr/bin/perl /usr/local/etc/route-change.pl > /dev/null 2>&1' >> /etc/crontab

# killall -HUP cron

 

Преимущество даного скрипта - простота и надежность.

Недостатком можно считать то, что он проверяет только доступность шлюза. В случае, если инет "упал" за шлюзом, переключение выполняться не будет. Как вариант - можно прописать статический маршрут к какому-то надежному серверу (например, к одному из серверов google.com)  через основной канал и выполнять проверку доступности именно этого сервера. Выполнить модификацию скрипта в таком случае не так уж и сложно...

Ваша оценка: Нет Средняя: 4.8 (6 голосов)

Добрый день низкий Вам поклон

Добрый день низкий Вам поклон за Ваш труд.

С Вашего разрешения пару вопросов ?

1 - ee /etc/rc.conf

ifconfig_fxp0="inet 192.168.1.1/24"
ifconfig_fxp1="inet 192.168.5.2/30"
ifconfig_fxp2="inet 192.168.6.2/30"
defaultrouter="192.168.213.129"
defaultrouter="192.168.178.209"

Какой шлюз комментить в кц конфе.Я так понимаю второй или его писать не надо и скрипт сам поменяет первый на второй ?

 

2 - Как быть с натом ? Он же висит на одном интерфейсе скрипт сам переключит на другой ?

 

3 - Как быть с фаерволом ?

 

#!/bin/sh
FwCMD="/sbin/ipfw -q  "

LanOut="fxp0"
IpOut="192.168.1.1"

IpIn="192.168.5.2"
LanIn="fxp1"

IpIn2="192.168.6.2"

IpIn2="fxp2"

Как скрипт переключит нужные сетевухи или как правильно прописать в фаерволе все сразу.

 

Ещё раз прошу помощи и поподробнее если будет желание ответить.

                С огромным уважением.
 

1. defaultrouter - оставляете

1. defaultrouter - оставляете только "главный" канал.

Для управления маршрутами используется стандартный демон маршрутизации route. Опция defaultrouter="192.168.213.129" указывает на необходимость выполнения следующей команды:

# route add default 192.168.213.129

Скрипт же будет проверять доступность шлюза и в случае необходимости переходить на резервный канал. Тоесть, фактически выполнится команда:

# route change default 192.168.178.209

 

2. Я сразу подымаю НАТ на двух интерфейсах (использую pf, либо же ipnat - без проблем НАТят на двух интерфейсах одновременно).

3. Это уже зависит от конфигурации файрвола. Нужно, чтобы можно было "ходить" и в один и в другой канал без изменения конфигурации. Либо же "пилить" скрипт под свои нужды, чтобы он выполнял необходимые изменения.

Re: Добрый день низкий Вам поклон

Странно, зачем писать на перле, если можно просто на баше?

Ведь там никаких особо функций не нужно особенных.

Re: Добрый день низкий Вам поклон

Писать можна на чем угодно. Главное, чтобы работало правильно. :)

а почему бы не использовать

а почему бы не использовать утилиту ping, вместо модуля Net::Ping?вы же используете утилиты netstat и route? 

Писал скрипт не я, только

Писал скрипт не я, только немножно допилил.

Кстати, если использовать Net::Ping::External, то нету никаких проблем с ложным срабатыванием (заменил в статье).

Re: Писал скрипт не я, только

Доброго времени суток, у меня 3 интерфейса: 1 L2TP(Медовый) 2 PPPoE(Яичный) 3 (Локалка).

Роняю первый, в crone скрипт отробатывает и переключает шлюз на 2.

Проходит минута и Use of uninitialized value in string ne at /usr/local/etc/route-change.pl line 40. if($b[1] ne $gw){

После этого дефаулт шлюзом становиться шлюз локалки яичного првайдера а не шлюз PPPoE (как хотелось-бы).

Куда копать? В Perle не разбираюсь.

Re: Писал скрипт не я, только

Топайте на форум. Создавайте тему, и предоставьте листинг скрипта и вывод ifconfig с комментариями.

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".

Вставай, Україно!

Литература