LinuxForum.Fans
Тема

Резервный канал с openVPN

Автор: u__________12 31 сообщений 8378 просмотров
#203849

Стоит такая задача.

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

Есть одна важная тонкость. На шлюзе поднят openVPN с другим оффисом,
нужно чтобы он работал. И нужно другому оффису тоже как-то автоматически
сообщить о смене ip/порта.

---------

Как сделать просто переключение в принципе представляю, гугл полон
подобными решениями, а вот как ещё и VPN поднимать, пока вообще в голову не
возьму.

#203851

перепрошить роутер железный? Пробовали капать в эту сторону?

#203881

Имхо не вариант. Там дещёвка, он на случай войны, подключен к другому прову.

Кое-что накопал.. и такой вопрос. При смене интерфейсов, Vpn достаточно будет перезапустить и он за работает по маршруту который в данный момент?

#205261

Помучил гугл. Вот такой вариант больше всего нравится http://sys-adm.org.ua/net/routing.php

2 вопроса: вот это

text
 # iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE

в какой файл пишется?

И

Сергей В. написал:
При смене интерфейсов, Vpn достаточно будет перезапустить и он за работает по маршруту который в данный момент?
#222919

[console]#!/bin/bash
gw1=первый
gw2=второй
#site='google.ru'
log='/var/log/check_gateway.log'

current=$(route -n | tail -1 | awk '{print $2}'); # Проверяем маршрут по умолчанию
if ping -c 4 $gw1 > /dev/null 2>&1; # Пингуем инет
then
if [ $gw1 = $current ]
then
exit 0
else
route del default 2> /dev/null
route add default gw $gw1
echo "Работает основной канал" >> $log
exit 0
fi
else
if [ $gw2=$current ]
then
exit 0
else
route del default 2> /dev/null;
echo "Внимание! Произошло падение основного канала!" >> $log
route add default gw $gw2
echo "Внимание!Работает резервный канал!" >> $log
fi
fi[/console]

вот скриптик, работает, но вопрос, как его зациклить в bash? в sh вот такой вариант http://sys-adm.org.ua/net/routing.php . Команды будут отличаться?

#222923

Я понимаю что нужно сделать 2 функции, вопрос лишь в том, что синтаксис в данном случае не будет различаться с sh?

#222927

[console]#!/bin/bash
gw1=первый
gw2=второй
check_period="30s"
#site='google.ru'
log='/var/log/check_gateway.log'
start_function ()
{
current=$(route -n | tail -1 | awk '{print $2}'); # Проверяем маршрут по умолчанию
if ping -c 4 $gw1 > /dev/null 2>&1; # Пингуем инет
then
if [ $gw1 = $current ]
then
exit 0
else
route del default 2> /dev/null
route add default gw $gw1
echo "Работает основной канал" >> $log
exit 0
fi
else
if [ $gw2=$current ]
then
exit 0
else
route del default 2> /dev/null;
echo "Внимание! Произошло падение основного канала!" >> $log
route add default gw $gw2
echo "Внимание!Работает резервный канал!" >> $log
fi
fi
}
while
do
start_function
sleep ${check_period}
done
[/console]

Так правильно? проверять на данный момент нет возможности

#222932

конкретно боюсь за цикл
[console]while
do
start_function
sleep ${check_period}
done[/console]

я скобки не ставил бы это правильно?

#223136
Сергей В. написал:
Так правильно? проверять на данный момент нет возможности

читать очень сложно без отступов. Поставьте себе нормальный редактор вроде kate.

Сергей В. написал:
я скобки не ставил бы это правильно?

конечно правильно. В качестве скобок тут do & done. Фигурные скобки в bash'е ставятся только
1. для ограничения функций
2. для ограничения переменных (их имени. Например вот так пишется переменная X, и сразу после неё Y: ${X}Y )
3. для подстановок-перечислений, вроде echo {1..10}
Круглые скобки почти всегда используются для создания отдельного процесса. например
[console]$ ( cd SOURCE; tar -cf - ) | ( cd TARGET; tar -xf - )[/console]
здесь одновременно работают три процесса - родительский, первый дочерний, который упаковывает файлы в поток, и второй дочерний, который этот поток сразу-же распаковывает. При этом каждый из tar'ов работает в своём собственном рабочем каталоге.

#223138
Сергей В. написал:
[$gw2=$current]

здесь ошибка.

Пожалуйста 2 простых правила:
1. пробелы в bash'е (не) ставят не только и не столько для красоты, они служат разделителем. Вы пробелов не поставили, потому $gw2=$current это ОДНА лексема. А [ ждёт три. (точнее 4 - ещё закрывающую скобку). Правильно так

text
[ $gw2 = $current ]

тут команда [ получила свои 4 лексемы, как и ожидала.
2. А если какая-то переменная пуста? Мы опять получаем не 4 лексемы, а меньше(или наоборот больше, если в переменных есть пробелы, и они не пусты, или получим неверный результат, ибо 2 пробела равны одному). Используйте двойные кавычки:

text
[ "$gw2" = "$current" ]

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

Из правила 1 есть исключение, которое только подтверждает правило. Это инициализация. Она пишется одной лексемой, без всяких пробелов. Ибо единая конструкция. И без начального $, ибо тут не значение переменной используется, а только её имя. Значение теряется.

Если не получается воспользоваться правилом 2 - используйте конкатенацию строк - две строки записанные слитно воспринимаются как единая лексема:

text
echo '!$'"$VARIABLE"'$!'

тут сцепка трёх строк слитно. Это одна лексема - строка.

Сергей В. написал:
exit 0

1. сама структура программы непродуманная. Нарисуйте блок-схему что-ли... Зачем тут вообще exit?
2. exit 0 нужно писать тогда, и только тогда, когда вы ЛЮТО, БЕШЕНО УВЕРЕНЫ, что надо именно 0. Вы уверены? Тогда ничего не пишите. А вдруг не ноль?
Вообще выходить из подпрограммы по exit - моветон. Выходить надо по коду возврата. Кстати о кодах возврата:
0..63 зарезервированы за системой. Системные утилиты возвращают коды с таким значением.
128..255 возвращаются тогда, когда программа была прервана. Код зависит от прервавшего сигнала. (можно по нему понять, было-ли это делением на ноль, или скажем CTRL+C).
вам остаются коды 64..127 Ну и код 0 конечно == "всё хорошо".

Сергей В. написал:
while

тут тоже ошибка - while это оператор проверки условия, ему нужна ещё одна лексема - для проверки. Например можно написать так

text
while true
do
# ...
done

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

#223198

Спасибо огромное, буду править

#223207

[console]#!/bin/bash
gw1=****; # Основной шлюз
gw2=****; # Резервный шлюз
check_period="30s"; # Периодичность запуска скрипта
log='/var/log/check_gateway.log'; # Путь к файлу логов
# Собственно сама функция проверки и переключения на резерв и обратно
start_function ()
{
current=$(route -n | tail -1 | awk '{print $2}'); # Проверяем маршрут по умолчанию
if ping -c 4 $gw1 > /dev/null 2>&1; # Пингуем инет
then
if [ $gw1 = $current ]; # Если используется основной шлюз, то выходим
then
return
else; # Если же нет то
route del default > /dev/null; # Сбрасываем резервный маршрут
route add default gw $gw1; # Прописываем основной
echo "Работает основной канал" >> $log
date >> $log
return; # Выходим
fi
else; # Если основной шлюз не доступен то
if [ $gw2 = $current ]; # Проверяем установлен ли резервный маршрут
then
return
else; # Если нет, то устанавливаем
route del default > /dev/null; # Сбрасываем основной маршрут
echo "Внимание! Произошло падение основного канала!" >> $log
route add default gw $gw2; # Прописываем резервный
echo "Внимание!Работает резервный канал!" >> $log
date >> $log
fi
fi
}
while true; # Зацикливаем скрипт с паузой.
do
start_function
sleep $check_period
done
[/console]

так будет работать?
Прошу прощения, просто я не программист ни разу.. но учусь.

И ещё.. чисто эстетика
[console]check_period="30s"
log='/var/log/check_gateway.log'[/console]

Какие кавычки можно ставить, или вообще не ставить?

#223278
drBatty написал:
читать очень сложно без отступов

Я сам под вендой сижу (работа)а к никсу подключаюсь через putty, вам даю вывод команды cat

#223338
Сергей В. написал:
if [ $gw1 = $current ]; # Если используется основной шлюз, то выходим

вот здесь нужны "двойные кавычки".

Сергей В. написал:
check_period="30s"
log='/var/log/check_gateway.log'
Какие кавычки можно ставить, или вообще не ставить?

1. лучше всего ставить одиночные 'кавычки'. Информация в них никак не обрабатывается, и поступает "как есть". Все символы, кроме самой одиночной кавычки.

2. К сожалению, часто надо вставить в строчку переменную. Это невозможно в одиночных кавычках (т.к. $ считается простым символом). Тогда используют двойные. Однако следует учесть, что внутри двойных кавычек раскрывается не только $, но и многие другие спец-символы. Вот доставляющий пример в интерактивном режиме:
[console]$ ping ya.ru
# пингуется...
$ echo "Hello World!!!"
echo "Hello Worldping ya.ru"
Hello Worldping ya.ru
[/console]
Дело в том, что "!" это тоже специальный символ, и он тоже раскрывается. Потому "программа" работает совсем не так, как ожидается.

3. можно совсем не использовать кавычек, и это даже работает. При этом надо помнить, что каждой команде bash'а нужен определённый набор лексем, и о том, что специальные символы bash будет раскрывать по своему. Из этого следует, что если ваш скрипт печатает что угодно, то и делать он будет что угодно. Что угодно составителю текста. Если это какой-нить простой текст, то скорее всего будет сообщение об ошибке, иначе - РЕШЕТО.

Сергей В. написал:
Я сам под вендой сижу (работа)а к никсу подключаюсь через putty, вам даю вывод команды cat

вы лучше скачайте файл, поправьте его в notepad++, и залейте обратно. Если нет аллергии к консоли - используйте FAR manager. Он ЕМНИП тоже умеет SSH. Там же можно копировать, и отступы сами расставляются. И подсветка, которая ловит 95% глупых ошибок (которых лично у меня было Over9000 первое время).

#224475

[console]#!/bin/bash
gw1=top secret; # Основной шлюз
gw2=top secret; # Резервный шлюз
check_period='30s'; # Периодичность запуска скрипта
log='/var/log/check_gateway.log'; # Путь к файлу логов
# Собственно сама функция проверки и переключения на резерв и обратно
start_function ()
{
current=$(route -n | tail -1 | awk '{print $2}'); # Проверяем маршрут по умолчанию
if ping -c 4 $gw1 > /dev/null 2>&1; # Пингуем инет
then
if [ $gw1 = $current ]; # Если используется основной шлюз, то выходим
then
return
else; # Если же нет то
route del default > /dev/null; # Сбрасываем резервный маршрут
route add default gw $gw1; # Прописываем основной
echo "Работает основной канал" >> $log
date >> $log
return; # Выходим
fi
else; # Если основной шлюз не доступен то
if [ $gw2 = $current ]; # Проверяем установлен ли резервный маршрут
then
return
else; # Если нет, то устанавливаем
route del default > /dev/null; # Сбрасываем основной маршрут
echo "Внимание! Произошло падение основного канала!" >> $log
route add default gw $gw2; # Прописываем резервный
echo "Внимание!Работает резервный канал!" >> $log
date >> $log
fi
fi
}
while true; # Зацикливаем скрипт с паузой.
do
start_function
sleep $check_period
done[/console]

Выкладываю окончательный вариант скрипта (хотя не совсем ))) )
Ну как? Будет работать?

#224511
Сергей В. написал:
Выкладываю окончательный вариант скрипта (хотя не совсем ))) )
Ну как? Будет работать?

не знаю. ну вышлите мне денег на ещё одного провайдера - попробую. Мне дома одного хватает wink
в любом случае, для тестирования, следует заменить >> $log на tee --append log
что-бы лог писался И в лог, И в консоль.

#232140

[console]
#!/bin/bash
gw1=194.186.251.137; # Основной шлюз
gw2=192.168.10.4; # Резервный шлюз
check_period='30s'; # Периодичность запуска скрипта
log='/var/log/check_gateway.log'; # Путь к файлу логов
# Собственно сама функция проверки и переключения на резерв и обратно
start_function ()
{
current=$(route -n | tail -1 | awk '{print $2}'); # Проверяем маршрут по умолчанию
if ping -c 4 $gw1 > /dev/null 2>&1; # Пингуем инет
then
if [ $gw1 = $current ]; # Если используется основной шлюз, то выходим
then
return
else
route del default > /dev/null; # Сбрасываем резервный маршрут
route add default gw $gw1; # Прописываем основной
echo "Работает основной канал" >> $log
date >> $log
return; # Выходим
fi
else
if [ $gw2 = $current ]; # Проверяем установлен ли резервный маршрут
then
return
else
route del default > /dev/null; # Сбрасываем основной маршрут
echo "Внимание! Произошло падение основного канала!" >> $log
route add default gw $gw2; # Прописываем резервный
echo "Внимание!Работает резервный канал!" >> $log
date >> $log
fi
fi
}
while true; # Зацикливаем скрипт с паузой.
do
start_function
sleep $check_period
done
[/console]

Вот так работает, но буду ещё допиливать. Надо VPN поднимать и ещё койчего не нравтся

#232150

В результате тестирования выявлен существенный недостаток.

Если основной шлюз недоступен, то каждые 30 сек скрипт сбрасывает резервный маршрут, а потом снова его прописывает. И получается, что резервный инет работает через "пень-колоду"..

#232158

Получается что не работает эта конструкция

#!/bin/bash
gw1=194.186.251.137; # Основной шлюз
gw2=192.168.10.4; # Резервный шлюз
check_period='30s'; # Периодичность запуска скрипта
log='/var/log/check_gateway.log'; # Путь к файлу логов
# Собственно сама функция проверки и переключения на резерв и обратно
start_function ()
{
current=$(route -n | tail -1 | awk '{print $2}'); # Проверяем маршрут по умолчанию
if ping -c 4 $gw1 > /dev/null 2>&1; # Пингуем инет
then

if [ $gw1 = $current ]; # Если используется основной шлюз, то выходим
then
return
else
route del default > /dev/null; # Сбрасываем резервный маршрут
route add default gw $gw1; # Прописываем основной
echo "Работает основной канал" >> $log
date >> $log
return; # Выходим
fi
else
if [ $gw2 = $current ]; # Проверяем установлен ли резервный маршрут
then
return

else
route del default > /dev/null; # Сбрасываем основной маршрут
echo "Внимание! Произошло падение основного канала!" >> $log
route add default gw $gw2; # Прописываем резервный
echo "Внимание!Работает резервный канал!" >> $log
date >> $log
fi
fi

#232163

И кстати.. простите за тупой вопрос, но как скрипт остановить??

kill check_gateways не прокатил

Войдите или зарегистрируйтесь, чтобы ответить.