LINUX.ORG.RU
ФорумAdmin

Резервирование каналов

 , ,


1

1

Приветсвую! Есть почтовый сервер с двумя сетевухами, каждая смотрит в сторону своего провайдера. Назовем так eth0 основной канал (быстрый), eth1 резервный канал (медленный). Задача такая. Постоянно сидим на быстром канале, если канал отрубился и находится в дауне как минимум 20 сек, перепрыгиваем на резервный (медленный). Если основной канал вернулся, возвращаемся обратно. Сначала думал поиграть с метриками в маршрутах, а нет тупик. Может типа скрипта который будет запускатся каждые 20 сек?

ping 8.8.8.8 -I eth0
if echo "Destination Host Unreachable"
   {
    ifconfig eth0 down;
    ifconfig eth1 up;
   }
   else
   {
    ifconfig eth0 up;
    ifconfig eth1 down;   
   }

Пример конечно весьма условный, но думаю суть понятна. Или есть более правильные пути?

дык достаточно менять адрес шлюза по умолчанию. Зачем сами интерфейсы дергать?

Тем более, что положив eth0 ты уже через него ничего не протестируешь.

А вот как тестировать «живость» интерфейса - это уже совсем другой вопрос.

vel ★★★★★
()
Ответ на: комментарий от firkax

Round-robin? Но вы отчасти правы, если вопрос про внешних клиентов (не сервера, а именно клиентов) то всё может быть не так однозначно, бывает что оффтопик «не очень» с этим справляется.

anc ★★★★★
()
Ответ на: комментарий от anc

дык достаточно менять адрес шлюза по умолчанию. Зачем сами интерфейсы дергать? Тем более, что положив eth0 ты уже через него ничего не протестируешь. А вот как тестировать «живость» интерфейса - это уже совсем другой вопрос.

ОК, меняем маршрут. Говорим ходить через иной шлюз?

Куда ты там перепрыгивать сам по себе собрался? Клиенты откуда узнают что адрес сервера меняется туда-сюда?

Не хотел про клиентови писать, что бы не грузить лишней информацией. Клиенты сидят в локальной сети. У почтовика есть третий интерфейс, о котором я «забыл» сообщить. Тот самый который смотрит в локалку. Так что для внутренних клиентов ничего не меняется. Для внешних клиентов немного по другому. Они стучатся на сервак по доменному имени. У хостера в ДНС зоне прописываем две MX-записи (у каждой МХ своя «А» запись со своим ip адресом) работающие по приоритету: если ip с более высоким приоритетом не работает, то письмо будет отправлено на следующий по приоритету. Как то так.

Вопрос тестирования интерфейса на «живость» остается открытым.

Humaxoid
() автор топика
Ответ на: комментарий от Humaxoid

Решение просто:
  настроить маршрутизацию для пингуемых IP-адресов
  через нужный интерфейс.

  Если, например, будем определять живость интерфейса
  пингуя адрес 8.8.8.8,
  то нужно настроить маршрутизацию для 8.8.8. через 
  этот интерфейс...
  Лучше, конечно, пинговать несколько адресов...

ru_org_linux
()
Ответ на: комментарий от AVL2

Нашел любопытный скрипт который меняет дефолтовый шлюз в таблице маршрутов при пропадании основного канала. Расписал комментарии так, как сам понял его работу. Понимание не полное, так как скрипт не заработал. Поправьте если что не так.

#!/bin/bash

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

GW_DEFAULT="11.22.33.44"  # IP шлюза на основном канале
IF_DEFAULT="eth0"         # Интерфейс основного канала
GW_BACKUP="55.66.77.88"   # IP шлюза на резервном канале
IF_BACKUP="eth2"          # Интерфейс резервного канала

# Определяем текущий шлюз
GW_CURRENT=$(route -n | grep -E "^0.0.0.0 .* UG .*" | awk '{print $2}')

# Пингуем контрольный хост
PINGS=$(ping -c 5 -i .5 -w 6 -I ${IF_DEFAULT} 8.8.8.8 | grep "packets transmitted" | awk '{print $4}')
# Где:
# -c количество пакетов для отправки
# -i интервал в секундах между отправкой пакетов

if [ "${GW_CURRENT}" == "${GW_DEFAULT}" ];   # если текущий шлюз является основным
  then
    if [ "${PINGS}" -le "5" ]; then
        echo "Переход на резервный маршрут"
        route del default
        route add default gw ${GW_BACKUP} ${IF_BACKUP}
    fi
  else
    if [ "${PINGS}" -gt "5" ]; then
      echo "Возврат к основному маршруту"
      route del default
      route add default gw ${GW_DEFAULT} ${IF_DEFAULT}
    fi
fi

Разъясните пожалуйста действие этой строки?

PINGS=$(ping -c 5 -i .5 -w 6 -I ${IF_DEFAULT} 8.8.8.8 | grep "packets transmitted" | awk '{print $4}')
И эти условия
if [ "${PINGS}" -le "5" ];
if [ "${PINGS}" -gt "5" ];
Спасибо большое!

Humaxoid
() автор топика
Последнее исправление: Humaxoid (всего исправлений: 1)
Ответ на: комментарий от Humaxoid

пингует шлюз основного канала .. этой строки?

нет, пингует 8.8.8.8 через интерфейс основного канала

И этой

если полученных пакетов меньше или равно 5

больше 5

yandrey
()
Последнее исправление: yandrey (всего исправлений: 2)
Ответ на: комментарий от Humaxoid

Само по себе решение узкое.

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

https://shorewall.org/MultiISP.html

Как вариант, настроить его через system-networkd

В этом случае без проблем можно пользоваться обоими каналами сразу, тестировать оба канала и включать/выключать через ip rule.

AVL2 ★★★★★
()
Ответ на: комментарий от yandrey

Спасибо! Сейчас резервирование работает. При пропадании основного канала, перепрыгивает на резервный. Другая беда нарисовалась, при появлении основного канала, не возвращается обратно. Запускается данный скрипт через крон, с переодичностью 3 мин.

#!/bin/bash

# Скрипт пингует удаленный хост 8.8.8.8 через основной канал и смотрит сколько пингов вернулось.
# Если мы на основном канале потерялось больше двух пакетов из шести, то переключается на резервный.
# Если мы на резервном и на основном потерялось меньше двух пингов, то переключаемся обратно на основной.

GW_DEFAULT="11.22.33.44" # IP шлюза на основном канале
IF_DEFAULT="eth0"        # Интерфейс основного канала - ТТК
GW_BACKUP="55.66.77.88"  # IP шлюза на резервном канале
IF_BACKUP="eth2"         # Интерфейс резервного канала - Freedom

# Определяем текущий шлюз
GW_CURRENT=$(route -n | grep -E "^0.0.0.0 .* UG .*" | awk '{print $2}')

# Пингуем контрольный хост
PINGS=$(ping -c10 -w30 -I ${IF_DEFAULT} 8.8.8.8 | grep "icmp_req=" | wc -l)

# Где:
# -c 10 отправляем только 10 пакетов
# -i 20 отправляем пакет каждые 20 секунд
# -w 30 пинговать не более 30 секунд
# -I интерфейс

if [ "${GW_CURRENT}" == "${GW_DEFAULT}" ];  then         # если текущий шлюз равен основному шлюзу, тогда проверим условие ниже

    if [ "${PINGS}" -le "3" ];  then                     # если полученных пакетов меньше или равно 3, тогда...
        echo "Переход на резервный маршрут"
        route del default
        route add default gw ${GW_BACKUP} ${IF_BACKUP}
    fi
else                                                     # иначе
    if [ "${PINGS}" -gt "3" ];  then                     # если полученных пакетов больше 3, тогда...
      echo "Возврат к основному маршруту"
      route del default
      route add default gw ${GW_DEFAULT} ${IF_DEFAULT}
    fi
fi

Humaxoid
() автор топика
Ответ на: комментарий от Humaxoid

На резервном канале при работающем осном ответы ping -I eth0 8.8.8.8 есть?

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

yandrey
()
Ответ на: комментарий от yandrey

На резервном канале при работающем осном ответы ping -I eth0 8.8.8.8 есть?

Если работает основной, на резервном пингов нет. Потому как в таблице маршрутов по дефолту установлен шлюз основного правайдера. И наоборот, если работает резервный канал, через основной канал пинги не ходят, по тойже причине.

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

Мне и не нужен снаружи доступ к нему, все юзеры сидят в локалке. Почта исходящаа и входящая при резервировании по любому бегает (про приоритеты МХ записей я писал выше). Городить полноценный мультиван под мои требования? Зачем? Вот как раз таки пинговать провайдерский шлюз не лучшее решение. Т.к возможны случаи что если у провайдера интернет отвалится, шлюз останется доступным. Что пинговать, это всё лирика. Не в этом вопрос.

Humaxoid
() автор топика
Ответ на: комментарий от Humaxoid

Парни, спасибо за помощь! Нашел ошибку. Нужно было пинговать не с основного интерфейса, а с текущего. Но перед этим определить через какой интерфейс на данный момент работаем. Для этого пришлось создать еще одну строку кода.

IF_CURRENT=$(route -n | grep -E "^0.0.0.0 .* UG .*" | awk '{print $8}')

Humaxoid
() автор топика
Последнее исправление: Humaxoid (всего исправлений: 1)
Ответ на: комментарий от Humaxoid

Тогда уж надо делать все по современному и компактней, этот скрипт, наверно, писался в 2000x)

...

GW_CURRENT=$(ip route | awk '/^default/ { print $3 }')

...

IF_CURRENT=$(ip route | awk '/^default/ { print $5 }')

...
    if [ "${PINGS}" -le "3" ];  then
        echo "Переход на резервный маршрут"
        ip route replace default via ${GW_BACKUP} dev ${IF_BACKUP}
    fi
else
    if [ "${PINGS}" -gt "3" ];  then
      echo "Возврат к основному маршруту"
      ip route replace default via ${GW_DEFAULT} dev ${IF_DEFAULT}
    fi
...

Городить полноценный мультиван под мои требования? Зачем?

Хотя бы, чтобы пришедшее на интерфейс, на него и возвращалось, независимо default он или нет.

yandrey
()
Последнее исправление: yandrey (всего исправлений: 1)
Ответ на: комментарий от yandrey

ip route replace default via ${GW_BACKUP} dev ${IF_BACKUP}

Изначально тоже думал об изменени маршрута. replace c cамого начала не сработал. Возвращает RTNETLINK answers: No such process. Пришлось городить огород (удаление дефолтового маршрута + добавление нового шлюза)

Humaxoid
() автор топика