Есть офисный маршрутизатор на базе 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 # perl /usr/local/etc/route-change.pl # netstat -rn | grep default |
Все работает! Осталось только проверить, происходит ли обратное переключение на основной канал:
# ipfw 1 delete # perl /usr/local/etc/route-change.pl # netstat -rn | grep default |
Проверим, ведется ли логгирование переключений:
# 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) через основной канал и выполнять проверку доступности именно этого сервера. Выполнить модификацию скрипта в таком случае не так уж и сложно...
Добрый день низкий Вам поклон
Добрый день низкий Вам поклон за Ваш труд.
С Вашего разрешения пару вопросов ?
1 - ee /etc/rc.conf
Какой шлюз комментить в кц конфе.Я так понимаю второй или его писать не надо и скрипт сам поменяет первый на второй ?
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" указывает на необходимость выполнения следующей команды:
Скрипт же будет проверять доступность шлюза и в случае необходимости переходить на резервный канал. Тоесть, фактически выполнится команда:
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 с комментариями.