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

В одном из филиалов один общеизвестный оператор, а в нашем случае еще и монополист (не будем называть имен) поставлял отвратительные услуги связи. Падение канала связи на 4 часа являлось нормой, а пускать других он отказывался. В конечном итоге была достигнута договоренность о приходе еще одного оператора на условиях, что мы продолжаем пользоваться их услугами.

В итоге мы получили на входе двух операторов, а так как первоначально на шлюзе было только две сетевухи (одна смотрела внутрь, другая наружу), пришлось добавлять еще одну. Далее все рулиться скриптом, который переключает каналы при падении одного из них. Скрипт был найден на просторах интернета и подправлен под наши нужды.

#!/bin/sh

###################################################
# Оригинал взят отсюда - хttp://polegin.ru/?cat=9 #
# Исходный скрипт был для Linux, я же переделал   #
# его под BSD и убрал поддержку iptables.         #
###################################################


PATH="/bin:/sbin:/usr/bin:/usr/sbin";

#Основной канал
isp1  ="xxx.xxx.xxx.xxx";
isp1gw="xxx.xxx.xxx.xxx";
 
#Резервный канал
isp2  ="yyy.yyy.yyy.yyy";
isp2gw="yyy.yyy.yyy.yyy";

# где isp1 и isp2 наши внешние адреса, а isp1gw и isp2gw соответственно адреса их шлюзов
#Адреса для проверки
defaultgw=${isp1gw};

ipping="8.8.8.8";          # DNS Google
ipping2="208.80.152.201";     # wikipedia.org
ipping3="192.168.13.12";     # Головной офис
ipping4="93.158.134.11";      # Yandex

# Проверяем статические маршруты до контрольных точек.
# Если их нет прописываем необходимые маршруты до хостов по доступности которых мы контролируем каналы.

netstat -rn | grep -q ${ipping};
if [ $? != 0 ];
    then
    route add -host ${ipping} ${defaultgw};
    fi

netstat -rn | grep -q ${ipping3};
if [ $? != 0 ];
    then
    route add -host ${ipping3} ${defaultgw};
    fi

netstat -rn | grep -q ${ipping4};
if [ $? != 0 ];     
    then
# !Маршрут для резервного канала!
    route add -host ${ipping4} ${isp2gw};
    fi

# Смотрим по какому каналу работаем (смотрим шлюз по умолчанию)
netstat -rn | grep "^default" | grep -q "${defaultgw}\>";
if [ $? != 0 ];
    then
    echo "Use ${isp2gw} GW, start test...";
 
# Пингуем хост ipping через default GW, что бы проверить доступность основного канала.
        ping -c 1 -W 5 ${ipping} > /dev/null 2>&1;
            if [ $? != 0 ];
                then
                echo "Host ${ipping} not available.";

# Делаем контрольную проверку нашего внешнего ip на предмет поднятия канала Вдруг это гугл(8.8.8.8) нас обманул.
                ping -c 1 -W 5 ${ipping3} > /dev/null 2>&1;
                    if [ $? != 0 ];
                        then
                        echo "Host ${ipping3} not available.";
                        echo "Sovintel is temporarily out of service. Line problem. ";
                        exit 0;
                    else
                        echo `date` "Sovintel is now available! Host ${ipping3} is responding." >> /var/log/2chanel.log;
                    fi
            else
                echo `date` "Switched to default channel." >> /var/log/2chanel.log;    
            fi

# переключение на основной канал, если использовался запасной.        
    echo `date` "Sovintel is now available! Host ${ipping} is responding."
    route delete default;
    route add default ${defaultgw};
    /usr/local/etc/rc.d/openvpn restart
    exit 0;

    else

# Основной работающий блок:
# Работаем на основном канале - если все хорошо - завершаем скрипт.
        echo "Use ${isp1gw} GW, start test...";
        ping -c 1 -W 5 ${ipping} > /dev/null 2>&1;
            if [ $? != 0 ];
                then
                echo "Host ${ipping} not available.";
            else
                echo "Host ${ipping} is responding, good.";
                echo "Exit...";                
                exit 0
            fi

# Пингуем хост ipping2. Вдруг проблема с хостом а инет всё же работает.
# Пинга нет выполняем переключение канала. Пинг есть - прерываем выполнение скрипта.
            ping -c 1 -W 5 ${ipping2} > /dev/null 2>&1;
            if [ $? != 0 ];
                then
                echo "Host ${ipping2} not available.";

# Проверяем резервный канал на доступность.
                ping -c 1 -W 5 ${ipping4} > /dev/null 2>&1;
                    if [ $? != 0 ];
                        then
                        echo "Host ${ipping4} not available.";
                        echo "GARS is temporarily out of service.";
                        echo "All chanel is temporarily out of service.";                        
                        exit 0                        
                    else
                        echo "Host ${ipping4} is responding.";
                        echo "GARS line is ok.";                        

# Переключение на резервный канал и рестарт ovpn, если есть какие-то другие сервисы - можно добавлять сюда их перезапуск.
                        route delete default;
                        route add default ${isp2gw};
                        /usr/local/etc/rc.d/openvpn restart
                        echo `date` "Switched to spare channel." >> /var/log/2chanel.log;
                    fi

      else
          echo `date` "Host ${ipping2} is responding. Exit." >> /var/log/2chanel.log;
          exit 0
    fi
fi

Забиваем данный скрипт в крон и наслаждаемся =)

Также интересно:

В логах мы получим что-то подобное:

Wed Feb 29 16:22:21 MSK 2012 Switched to spare channel.
Wed Feb 29 17:16:00 MSK 2012 Switched to default channel.
Wed Feb 29 17:01:27 MSK 2012 Switched to spare channel.
Wed Feb 29 17:16:00 MSK 2012 Switched to default channel.
Wed Feb 29 17:03:12 MSK 2012 Switched to spare channel.
Wed Feb 29 17:06:14 MSK 2012 Switched to spare channel.
Wed Feb 29 17:16:00 MSK 2012 Switched to default channel.
Wed Feb 29 17:15:26 MSK 2012 Switched to spare channel.
Wed Feb 29 17:16:00 MSK 2012 Switched to default channel
.

Выражаем благодарность konikki за  надлежащее исполнение своих обязанностей =)

Интересное на сайте: 
0
Голосов пока нет

Комментарии

вообще то есть куча готовых решений один из вариантов описан тут h_ttp://www.ignix.ru/public/agregatsiya-kanalov-link-aggregation-trunking ЗЫ как то криво работают коменты, если я авторизован то я не могу их оставлять =((

вариантов решений много, никто и не говорил, что это самый лучший =)

по комментам, выйду с отпуска посмотрю

Привет, хотел взять твой скрипт за образец, но мне кажется в нем ошибка! Ты добавляешь статический маршрут до основного офиса: route add -host ${ipping3} ${defaultgw}; и потом ни где его не удаляешь! Соответственно при переключении на резервный канал этот хост будет не доступен, так как будет пытаться идти через основной!

Приветствую.
Маршрут удаляется и прописывается по новой перед каждой проверкой.
Прошу внимательно прочитать скрипт - комментарии на русском.
Так же хочу напомнить, что он всего лишь переделан под мою задачу, совершенно согласен, что в какой-либо другой ситуации, можно воспользоваться другой логикой.
route delete default;
    route add default ${defaultgw};
    /usr/local/etc/rc.d/openvpn restart