Mikrotik OS та автоматичне перемикання на резервний канал

Поділитись у:
*/?>

Нещодавно у зв'язку з переходом з ADSL на Ethernet представилася чудова можливість спробувати обладнання від Mikrotik. У зв'язку з чим був куплений роутер RB750GL . Залізниця виявилася чудовою як зовні, так і з погляду функціоналу та надійності.

У результаті я залишив обидва канали і вирішив налаштувати резервування з автоматичним перемиканням. Стандартні засоби перемикання шлюзів не покривають все різноманіття збоїв, тому потрібно писати свої скрипти.

Конфігурація мережі


1. Канал Ehernet від NLink встромляється в перший порт роутера, отримує IP DHCP і піднімає pptp з'єднання, назване nlink. Це буде основне з'єднання.
2. Канал ADSL від провайдера Домолінк проходить через DLink-2500 в режимі моста і встромляється в другий порт роутера, поверх піднімається pppoe з'єднання, назване domolink. Це буде резервне з'єднання.
3. Порти 3-5 роутера використовуються для підключення пристроїв локальної мережі.

Налаштування роутера


Налаштування підключень і маскарадингу для комп'ютерів локальна мережа є тривіальною і детально описана в офіційній вікі .

При налаштуванні ppp підключень потрібно відключити додавання маршрутів за замовчуванням, а потім створити статичні маршрути різними метриками та відповідними коментарями:
/ip route
add comment=MainGW disabled=no distance=1 dst-address=0.0.0.0/0 gateway=nlink scope=30 target-scope=10
add comment=RsrvGW disabled=no distance=2 dst-address=0.0.0.0/0 gateway=domolink scope=30 target-scope=10

Тепер щоб перемикати канали, достатньо змінювати параметр distance. Трафік піде через канал із меншим значенням цього параметра.

Скрипти

Встановлення глобальних параметрів під час запуску роутера


Скрипт називається set_global_parameters
#Main interface name
:global MainIf nlink
#Reserve interface name
:global RsrvIf domolink
#Main interface ip address
:global MainIfAddress ""
#Reserve interface ip address
:global RsrvIfAddress ""

Визначення IP-адрес інтерфейсів

Визначення IP-адреси основного інтерфейсу


Скрипт називається define_main_if_ip
:global MainIf
:global MainIfAddress ""
:set MainIfAddress [/ip address get [find interface=$MainIf] address]

Цей скрипт визначає IP-адресу основного інтерфейсу для доступу до Інтернету. Якщо цей інтерфейс відсутній, то скрипт завершуватиметься з помилкою, а в змінній MainIfAddress буде порожній рядок.

Визначення IP-адреси резервного інтерфейсу


Скрипт називається define_reserved_if_ip
:global RsrvIf
:global RsrvIfAddress ""
:set RsrvIfAddress [/ip address get [find interface=$RsrvIf] address]

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

Перемикання каналів


Скрипт називається connection_check
:global MainIf
:global RsrvIf
:global MainIfAddress
:global RsrvIfAddress

:local PingCount 3

#www.ru
:local PingTarget1 194.87.0.50

#ya.ru
:local PingTarget2 87.250.250.203

#google dns
:local PingTarget3 8.8.8.8

#Check main internet connection
:local MainIfInetOk false;

if ($MainIfAddress="") do={delay 5}

if ($MainIfAddress!="") do={
:local PingResult1 [/ping $PingTarget1 count=$PingCount interface=$MainIf]
:local PingResult2 [/ping $PingTarget2 count=$PingCount interface=$MainIf]
:local PingResult3 [/ping $PingTarget3 count=$PingCount interface=$MainIf]

:set MainIfInetOk (($PingResult1 + $PingResult2 + $PingResult3) >= (2 * $PingCount))
}

#Check reserved internet connection
:local RsrvIfInetOk false;

if ($RsrvIfAddress="") do={delay 5}

if ($RsrvIfAddress!="") do={
:local PingResult1 [/ping $PingTarget1 count=$PingCount interface=$RsrvIf]
:local PingResult2 [/ping $PingTarget2 count=$PingCount interface=$RsrvIf]
:local PingResult3 [/ping $PingTarget3 count=$PingCount interface=$RsrvIf]

:set RsrvIfInetOk (($PingResult1 + $PingResult2 + $PingResult3) >= (2 * $PingCount))
}

:put "MainIfInetOk=$MainIfInetOk"
:put "RsrvIfInetOk=$RsrvIfInetOk"

if (!$MainIfInetOk) do={
/log error "Main internet connection error"
}

if (!$RsrvIfInetOk) do={
/log error "Reserve internet connection error"
}

:local MainGWDistance [/ip route get [find comment="MainGW"] distance]
:local RsrvGWDistance [/ip route get [find comment="RsrvGW"] distance]
:put "MainGWDistance=$MainGWDistance"
:put "RsrvGWDistance=$RsrvGWDistance"

#SetUp gateways
if ($MainIfInetOk && ($MainGWDistance >= $RsrvGWDistance)) do={
/ip route set [find comment="MainGW"] distance=1
/ip route set [find comment="RsrvGW"] distance=2
/log info "Switch to main internet connection"
}

if (!$MainIfInetOk && $RsrvIfInetOk && ($MainGWDistance <= $RsrvGWDistance)) do={
/ip route set [find comment="MainGW"] distance=2
/ip route set [find comment="RsrvGW"] distance=1
/log warning "Switch to reserve internet connection"
}


Зверніть увагу на пінг через конкретний інтерфейс, а також на критерій визнання каналу несправним. Я пінгую три різних вузла і вважаю, що інтернет на даному інтерфейсі не працює, якщо приходить менше 2/3 відповідей.

Планувальник


1. Скрипт set_global_parameters запускається один раз під час запуску роутера.
2. Скрипти визначення IP-адрес запускаються кожні 27 секунд. Таке значення вибрано, щоб мінімізувати кількість одночасних запусків із основним скриптом.
3. Скрипт connection_check запускається щохвилини.

Висновки


Отримане рішення при мінімумі витрат суттєво підвищило надійність моєї домашньої мережі та успішно справляється з найвитонченішими збоями місцевих провайдерів, при цьому воно достатньо захищене від збоїв зовнішніх вузлів мережі.

logo
Відгуки покупців
Рейтинг покупців
0 / 5
На основі N оцінок покупців
0%
0%
0%
0%
0%
Відгук
Відмінно
Заголовок*
Достоїнства
Недоліки
Коментар*
Як вас звати

Повернення до списку


Авторизуйтеся, щоб додати відгук

x