#!/usr/bin/perl -w
use strict;
use LockFile::Simple qw(lock trylock unlock);
require 'sys/syscall.ph';
# Устанавливаем путь по умолчанию
$ENV{PATH} = '/bin:/usr/bin:/sbin:/usr/sbin';
# Отладка
my $debug=1;
my $lockmgr = LockFile::Simple->make(-format => '%f',
-stale => 1, -autoclean => 1, -hold => 0,
-efunc => undef, -wfunc => undef);
my $lock = '/opt/change-route.lock';
sub quit {
# Помещаем сюда код для корректного
# прекращения работы
exit(0);
};
# Отделяемся от родителя
fork() && exit;
# Отключаемся от терминала
close STDOUT; close STDERR; close STDIN;
# Делаем корень текужим каталогом
chdir '/';
# Создаем новую сессию и становимся лидером
# группы процессов, чтоб нас случайно не прибили
syscall(&SYS_setsid);
# Блокировка (чтоб не запустилось одновременно 2 процесса)
exit 1 unless ($lockmgr->trylock($lock));
# Перехватываем сигналы, для корректного выхода
$SIG{'INT'} = $SIG{'QUIT'} = $SIG{'TERM'} = 'quit';
$SIG{'HUP'} = 'ignore';
# Основной канал
my %primaryip = (
iface => "eth1",
ip => "7.13.6.228",
netmask => "255.255.255.224",
route => "7.13.6.225"
);
# Резервный канал
my %secondaryip = (
iface => "eth2",
ip => "21.2.7.41",
netmask => "255.255.255.252",
route => "21.2.7.42"
);
# Ip для теста
my $testip='86.110.181.76';
# Локальная сеmь
my $iflocal='192.168.0.0/24';
# Правила для iptables
# основной канал
my $primaryrules = " -s $iflocal -o $primaryip{iface} -j SNAT --to-source $primaryip{ip}";
# резервный канал
my $secondaryrules = " -s $iflocal -o $secondaryip{iface} -j SNAT --to-source $secondaryip{ip}";
begin:
# Определение работающего канала
open(A,"route|");
my $activeiface='not';
while () {
next if (!($_ =~ m/default\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)/));
$activeiface=$1;
};
close(A);
# Проверка каналов
my $primarystatus=system("ping -c 2 -I $primaryip{ip} $primaryip{route} > /dev/null");
my $secondarystatus=system("ping -c 2 -I $secondaryip{ip} $secondaryip{route} > /dev/null");
system("route add -host $testip gw $primaryip{route} metric 30");
my $primarystatusya=system("ping -c 2 -I $primaryip{ip} $testip > /dev/null");
system("route del -host $testip gw $primaryip{route} metric 30");
system("route add -host $testip gw $secondaryip{route} metric 30");
my $secondarystatusya=system("ping -c 2 -I $secondaryip{ip} $testip > /dev/null");
system("route del -host $testip gw $secondaryip{route} metric 30");
open(LogFile,">> /opt/change-route.log");
if ($debug){
print LogFile "\n",`date`;
print LogFile "Активный канал ", $activeiface, "\n";
print LogFile "Основной канал ",$primaryip{iface},", шлюз ", $primaryip{route}, " ",
$primarystatus?"Недоступен":"Доступен", " ",$testip, " " , $primarystatusya?"Недоступен":"Доступен", "\n";
print LogFile "Резервный канал ",$secondaryip{iface},", шлюз ", $secondaryip{route}, " ",
$secondarystatus?"Недоступен":"Доступен", " ",$testip, " ", $secondarystatusya?"Недоступен":"Доступен", "\n";
};
# Переключение шлюза
# Если используется резервный канал, но доступен основной переключаемся на него
if ( ($activeiface eq $secondaryip{iface}) and ($primarystatusya == 0)) {
print LogFile "Переключаю на основной",$primaryip{iface}, "\n";
system("route del default gw $secondaryip{route}");
system("route add default gw $primaryip{route}");
system("iptables -t nat -D POSTROUTING $secondaryrules");
system("iptables -t nat -A POSTROUTING $primaryrules");
open (MAIL, '| /bin/mail -a
root@diapazon.org
7922ххххххх@sms.ugsm.ru');
print MAIL "Subject: ",`hostname`,"service info";
print MAIL `date`," Pereklyuchenie na osnovnoi kanal";
close (MAIL);
};
# Если используется основной канал, но он не работает переключаемся на резервный
if ( ($activeiface eq $primaryip{iface}) and (!($primarystatusya == 0)) ) {
# Смена маршрута поумолчанию на резервный, при доступности второго канала
if ($secondarystatusya == 0) {
print LogFile "Переключаю на резервный",$secondaryip{iface}, "\n";
system("route del default gw $primaryip{route}");
system("route add default gw $secondaryip{route}");
system("iptables -t nat -D POSTROUTING $primaryrules");
system("iptables -t nat -A POSTROUTING $secondaryrules");
open (MAIL, '| /bin/mail -a
root@diapazon.org
7922ххххххх@sms.ugsm.ru');
print MAIL "Subject: ",`hostname`,"service info";
print MAIL `date`," Pereklyuchenie na rezervnyi kanal";
close (MAIL);
};
};
close(LogFile);
sleep 120;
goto begin;