Переключение на резервный канал

Просмотров: 298

Есть два провайдера, и ты хочешь всегда быть онлайн? Тогда читай
Article Image

Всем здарофф. На работе год назад возникла необходимость сделать переключение на резервного провайдера, вот я и озадачился. Написал все на Dash (SH).

Допустим, у нас имеется ПК с тремя сетевыми картами, они все настроены и работают. Одна - локальная сеть, другие две - провайдеры. Один из провайдеров является предпочитаемым и используется по-умолчанию. Идея переключения состоит в том, чтобы проверять доступность некоторого хоста (в моем случае самого ip шлюза), и в случае недоступности переключаться на использование другого шлюза (ip route рулит). Также необходимо проверять и второй резервный шлюз, чтобы в случае его недоступности насрать в логи поругаться на сисадмина. И до кучи, во время работы через резервный шлюз проверять также и основной, и если он вдруг оживет, немедленно переключиться на него обратно. Вот так вот все просто, да? Ну да ладно, вода, вода, вода.... На тебе уже скрипт:

#!/bin/sh

# Путь к log-файлу
log="/var/log/routing.log"

# Задаем периодичность опроса шлюзов.
# 30s - 30 секунд
# 10m - 10 минут
# 1h - 1 час
check_period="30s"

# Если log-файл не найден, создаем его, иначе отчищаем
clear_log ()
{
if [ ! -f ${log} ]
then
touch ${log}
else
cat /dev/null > ${log}
fi
}

# Инициализируем переменные
init ()
{
gw1="ip_основного_шлюза"
gw2="ip_резервного_шлюза"
prefered_gw=${gw1}

dev_if1="eth1"
dev_if2="eth2"

if1=`ifconfig ${dev_if1} | awk -F ' *|:' '/inet addr/{print $4}'`
if2=`ifconfig ${dev_if2} | awk -F ' *|:' '/inet addr/{print $4}'`

# Текущие статусы шлюзов: 0 - шлюз недоступен, 1 - шлюз работает
gw1_curr_status=0
gw2_curr_status=0

# Текущие потери пакетов на шлюзе
gw1_curr_packet_loss=0
gw2_curr_packet_loss=0

# Максимальный процент потерь пакетов, при превышении данного числа, шлюз считается недоступным
gw1_max_packet_loss=35
gw2_max_packet_loss=40

# Отчищаем log-файл и сохраняем значения основных переменных
clear_log
echo `date +"%T %d.%m.%Y"`." Инициализация. Проверка шлюзов с периодичностью ${check_period}." >> ${log}
echo `date +"%T %d.%m.%Y"`." ШЛЮЗ 1 [if1=${if1}, dev_if1=${dev_if1}, gw1=${gw1}], ШЛЮЗ 2 [if2=${if2}, dev_if2=${dev_if2}, gw2=${gw2}]" >> ${log}
}

# Данная функция определяет текущее состояние каждого из шлюзов.
# Если текущий процент потерь меньше максимально допустимого, то считаем, что шлюз доступен.
get_current_status ()
{
echo `date +"%T %d.%m.%Y"`." Получаем текущий статус шлюзов." >> ${log}

# Статус шлюза 1
gw1_curr_packet_loss=`ping -I ${dev_if1} -c20 -l20 -q -W3 ${gw1} | grep loss | awk '{print $(NF-4)}' | cut -d"%" -f1`
if [ ${gw1_curr_packet_loss} -le ${gw1_max_packet_loss} ]
then
echo `date +"%T %d.%m.%Y"`. "ШЛЮЗ 1. [Статус - OK]. Потеряно пакетов на шлюзе ${gw1} via ${dev_if1} - ${gw1_curr_packet_loss}%." >> ${log}
gw1_curr_status=1
else
echo `date +"%T %d.%m.%Y"`. "ШЛЮЗ 1. [Статус - КРИТИЧЕСКИЙ!]. Потеряно пакетов на шлюзе ${gw1} via ${dev_if1} - ${gw1_curr_packet_loss}%." >> ${log}
gw1_curr_status=0
fi

# Статус шлюза 2
gw2_curr_packet_loss=`ping -I ${dev_if2} -c20 -l20 -q -W3 ${gw2} | grep loss | awk '{print $(NF-4)}' | cut -d"%" -f1`
if [ ${gw2_curr_packet_loss} -le ${gw2_max_packet_loss} ]
then
echo `date +"%T %d.%m.%Y"`. "ШЛЮЗ 2. [Статус - OK]. Потеряно пакетов на шлюзе ${gw2} via ${dev_if2} - ${gw2_curr_packet_loss}%." >> ${log}
gw2_curr_status=1
else
echo `date +"%T %d.%m.%Y"`. "ШЛЮЗ 2. [Статус - КРИТИЧЕСКИЙ!]. Потеряно пакетов на шлюзе ${gw2} via ${dev_if2} - ${gw2_curr_packet_loss}%." >> ${log}
gw2_curr_status=0
fi
}

# Данная функция производит переключение шлюза по умолчанию в зависимости от результатов полученных в get_current_status ()
# На данный момент предпочитаемым шлюзом может быть только ${gw1}
switch_default_gw ()
{
curr_gw=`ip route show | grep default | awk '{print $3}'`
if [ ${curr_gw} = ${prefered_gw} -a ${gw1_curr_status} -eq 1 ]
then
echo `date +"%T %d.%m.%Y"`. "[Статус - OK]. Предпочитаемый шлюз активен, ничего делать не буду." >> ${log}
return
fi

if [ ${curr_gw} = ${prefered_gw} -a ${gw1_curr_status} -eq 0 -a ${gw2_curr_status} -eq 1 ]
then
echo `date +"%T %d.%m.%Y"`. "Предпочитаемый шлюз ${gw1} недоступен. Переключение на ${gw2}" >> ${log}
echo `date +"%T %d.%m.%Y"`. "ip route replace default via ${gw2} dev ${dev_if2}" >> ${log}
/sbin/ip route replace default via ${gw2} dev ${dev_if2}
return
fi

if [ ${curr_gw} != ${prefered_gw} -a ${gw1_curr_status} -eq 1 ]
then
echo `date +"%T %d.%m.%Y"`. "Предпочитаемый шлюз ${prefered_gw} снова активен. Переключение с ${curr_gw} на ${prefered_gw}" >> ${log}
echo `date +"%T %d.%m.%Y"`. "ip route replace default via ${gw1} dev ${dev_if1}" >> ${log}
/sbin/ip route replace default via ${gw1} dev ${dev_if1}
return
fi

if [ ${curr_gw} != ${prefered_gw} -a ${gw1_curr_status} -eq 0 -a ${gw2_curr_status} -eq 1 ]
then
echo `date +"%T %d.%m.%Y"`. "Предпочитаемый шлюз ${prefered_gw} все еще оффлайн. Текущий шлюз ${gw2}" >> ${log}
return
fi

if [ ${gw1_curr_status} -eq 0 -a ${gw2_curr_status} -eq 0 ]
then
echo "*************************************************************************" >> ${log}
echo `date +"%T %d.%m.%Y"`. "ВНИМАНИЕ!!!. Оба шлюза недоступны. Это очень печально." >> ${log}
echo "*************************************************************************" >> ${log}
return
fi
}

# Инициализируем переменные
init

# "Заходим" в вечный цикл, в котором по очереди вызываем функции get_current_status () и switch_default_gw ()
# После этого делаем паузу, время паузы задается в переменной ${check_period}
while [ 1 ]
do
get_current_status
switch_default_gw
sleep ${check_period}
done

Можно пинговать не шлюз, а конкретный ip, который ТОЧНО всегда будет онлайн (привет, 8.8.8.8). Также можешь добавить в область переключения шлюзов дополнительные скрипты, например правила iptables (как у меня  на заводе). Много чего можно сделать, было бы желание=) 

Запускать скрипт нужно только один раз (например так /путь_к_скрипту &   (да да да, с & в конце, а то получишь консоль с вечным логом)) , а не "стопяцот" раз по Крону! Можешь запихать скрипт в автозагрузку. Ну вот как-то так. Работает. Есть предложения получше? Пиши, не стесняйся

Опубликовано 4 Декабря 2015 в категории SH (Dash)

comments powered by HyperComments
Поиск по сайту:

Теги:

Популярные статьи:

Новости IT:

^ Наверх