К основному контенту

Автоматическое переключение каналов на MikroTik RouterOS

Встроенная в MikroTik RouterOS функция обеспечения отказоустойчивости доступа в Интернет(имеется ввиду check-gateway=ping), имеет огромный недостаток: она проверяет доступность шлюза провайдера, а не доступность сети Интернет через этого провайдера.
Подобное решение для Linux я уже описывал, и это можно сказать его «порт» на RouterOS :) 

Имеем 3 канала в Интернет и один в локальную сеть(тут называется DMZ):
/ip address
add address=172.16.16.2/24 broadcast=172.16.16.255 comment=DMZ disabled=no \
    interface=ether1-dmz network=172.16.16.0
add address=80.X.255.130/26 broadcast=80.X.255.191 comment=RialKom \
    disabled=no interface=ether3-rialkom network=80.X.255.128
add address=212.152.X.55/26 broadcast=212.152.X.63 comment=Inet disabled=\
    no interface=ether5-inet network=212.152.X.0
add address=62.X.7.242/29 broadcast=62.X.7.247 comment=Beeline \
    disabled=no interface=ether4-beeline network=62.X.7.240
Основные маршруты, которые мы и будем переключать:
/ip route
add comment=GW_1 disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
    80.X.255.129 scope=30 target-scope=10
add comment=GW_2 disabled=no distance=2 dst-address=0.0.0.0/0 gateway=\
    62.X.7.241 scope=30 target-scope=10
add comment=GW_3 disabled=no distance=3 dst-address=0.0.0.0/0 gateway=\
    212.152.X.1 scope=30 target-scope=10
Клиенты должны маскарадиться:
/ip firewall nat
add action=masquerade chain=srcnat comment="" disabled=no src-address=172.16.16.0/24
Сам скрипт, называется CheckINET:
###################################################################
#Name:  CheckINET
#Version: 1.0.1
#Created: Andrey Orlov
#Email:  tangarus(a)gmail.com
#Web:  http://www.tangarus.ru/
#Date:  10.2009
#Description:Автоматическое переключение каналов на RouterOS
####################################################################
#set variables
:local PingCount 3
 
# www.ya.ru
:local IPToPing 77.88.21.8
 
:local SrcAddrA 80.X.255.130
:local SrcAddrB 62.X.7.242
:local SrcAddrC 212.152.X.55
 
#ping gateways with src
:local pingresultA [/ping $IPToPing count=$PingCount src-address=$SrcAddrA]
:local pingresultB [/ping $IPToPing count=$PingCount src-address=$SrcAddrB]
 
#if link_A is DOWN and link_B is UP then:
:if (($pingresultA=0) && ($pingresultB=$PingCount)) do={
 
:if ((([/ip route get [find comment="GW_2"] distance]=1)&&([/ip route get [find comment="GW_1"] distance]=2)&&([/ip route get [find comment="GW_3"] distance]=3))=false) do={
:log warning "set routes to B"
/ip route set [find comment="GW_2"] distance=1
/ip route set [find comment="GW_1"] distance=2
/ip route set [find comment="GW_3"] distance=3
}
}
 
#if link_A is UP and link_B is DOWN then:
:if (($pingresultA=$PingCount) && ($pingresultB=0)) do={
 
:if ((([/ip route get [find comment="GW_2"] distance]=2)&&([/ip route get [find comment="GW_1"] distance]=1)&&([/ip route get [find comment="GW_3"] distance]=3))=false) do={
:log warning "Set routes to A"
/ip route set [find comment="GW_1"] distance=1
/ip route set [find comment="GW_2"] distance=2
/ip route set [find comment="GW_3"] distance=3
}
}
 
#if link_A is DOWN and link_B is DOWN:
:if (($pingresultA=0) && ($pingresultB=0)) do={
 
:if ((([/ip route get [find comment="GW_2"] distance]=3)&&([/ip route get [find comment="GW_1"] distance]=2)&&([/ip route get [find comment="GW_3"] distance]=1))=false) do={
:log warning "Set routes to C"
/ip route set [find comment="GW_3"] distance=1
/ip route set [find comment="GW_1"] distance=2
/ip route set [find comment="GW_2"] distance=3
}
}
 
# Link A or Link B both are UP:
:if (($pingresultA=$PingCount) && ($pingresultB=$PingCount)) do={
 
:if ((([/ip route get [find comment="GW_2"] distance]=2)&&([/ip route get [find comment="GW_1"] distance]=1)&&([/ip route get [find comment="GW_3"] distance]=3))=false) do={
:log warning "Set routes to A"
/ip route set [find comment="GW_1"] distance=1
/ip route set [find comment="GW_2"] distance=2
/ip route set [find comment="GW_3"] distance=3
}
}
выполняем его раз в 30 секунд:
/system scheduler
add comment="" disabled=no interval=30s name=CheckINET on-event="/system script run CheckINET" policy=\
    reboot,read,write,policy,test,password,sniff,sensitive start-date=jan/01/1970 start-time=00:00:00
Казалось-бы всё, но есть один подводный камень: сейчас выполняя пинг /ping www.ya.ru src-address=212.152.X.55, RouterOS не будет обращать внимания на параметр 212.152.X.55 если этот шлюз недоступен.
Т.е. если он доступен то пакеты будут идти чрез него, но если нет, то через текущий default gw.
Чтобы избежать этого, необходимо помечать соединения на входе интерфейса соответствующей routing mark.
Параллельно это решит проблему «отвечать на тот интерфейс, на который пришел запрос»: сейчас пингуя интерфейс №2 ответы пойдут через интерфейс которому принадлежит default gw, и ответа мы не получим.
Добавляем маршруты в именованные таблицы маршрутизации:
/ip route
add comment="" disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
    80.X.255.129 routing-mark=rialkom scope=30 target-scope=10
add comment="" disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
    62.X.7.241 routing-mark=beeline scope=30 target-scope=10
add comment="" disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
    212.152.X.1 routing-mark=inet scope=30 target-scope=10
Правила маршрутазиции:
/ip route rule
add action=lookup comment="" disabled=no src-address=212.152.X.55/32 \
    table=inet
add action=lookup comment="" disabled=no src-address=62.X.7.242/32 table=\
    beeline
add action=lookup comment="" disabled=no src-address=80.X.255.130/32 \
    table=rialkom
эти правила нужны, чтобы из внутренней сети были всегда (в не зависимости от текущего рабочего канала) доступны сети провайдеров, я использую для мониторинга:
/ip route rule
add action=lookup comment="" disabled=no dst-address=62.X.7.240/29 table=\
    beeline
add action=lookup comment="" disabled=no dst-address=80.X.255.128/26 \
    table=rialkom
add action=lookup comment="" disabled=no dst-address=212.152.X.0/26 table=\
    inet
Обращаю внимание: routing-mark которые видны через WinBOX в MANGLE, это таблицы маршрутизации из /ip route (routing-table) и routing-mark'и, а routing-table там напрямую использовать нельзя!
Т.е. там по непонятным причинам отображаються как routing-mark, так и routing-table.
(UPD: А вот на другом роутере работает и так и так... Хм...)
Нужно их сопоставить:
/ip route rule
add action=lookup comment="" disabled=no routing-mark=rialkom table=rialkom
add action=lookup comment="" disabled=no routing-mark=beeline table=beeline
add action=lookup comment="" disabled=no routing-mark=inet table=inet
Помечаем белый краской спинки пакетиков:
/ip firewall mangle
add action=mark-routing chain=output comment="Local answer to correct if" disabled=no new-routing-mark=beeline \
    passthrough=yes src-address=62.X.7.242
add action=mark-routing chain=output comment="Local answer to correct if" disabled=no new-routing-mark=inet passthrough=\
    yes src-address=212.152.X.55
add action=mark-routing chain=output comment="Local answer to correct if" disabled=no new-routing-mark=rialkom \
    passthrough=yes src-address=80.X.255.130
Всё!

Спасибо TangaRUS !

Комментарии

Популярные сообщения из этого блога

Управление исходящей маршрутизацией вызовов Asterisk FreePBX

В данной статье рассматривается один из способов настройки исходящей маршрутизации средствами FreePBX с использованием шаблонов.  Управление исходящей маршрутизацией осуществляется на вкладке Connectivity > Outbound Routes Основными полями здесь являются: Route Name — имя маршрута, Dial patterns that will use this Route — здесь перечисляются шаблоны, используемые в данном маршруте, Trunk Sequence for Matched Routes — указываются маршруты используемые на этом направлении. В принципе этих полей достаточно для нормального функционирования исходящей маршрутизации. Шаблон — номер, некоторые цифры которого заменяются подстановочными символами и группами символов. Можно использовать следующие символы:  X — любая цифра 0 — 9; Z — любая цифра 1 — 9; N — любая цифра 2 — 9; [123] — любая из цифр, перечисленных в квадратных скобках. . — одна или неск...

Автообзвон на Asterisk (FreePBX)

Syntax of call files Specify where and how to call Channel : <channel>: Channel to use for the call. CallerID : «name» <number> Caller ID, Please note: It may not work if you do not respect the format: CallerID: «Some Name» <1234> MaxRetries : <number> Number of retries before failing (not including the initial attempt, e.g. 0 = total of 1 attempt to make the call). Default is 0. RetryTime : <number> Seconds between retries, Don't hammer an unavailable phone. Default is 300 (5 min). WaitTime : <number> Seconds to wait for an answer. Default is 45. Account : Set the account code to use. If the call answers, connect it here: Context : <context-name> Context in extensions.conf Extension : <ext> Extension definition in extensions.conf Priority : <priority> Priority of extension to start with Set : Set a variable for use in the extension logic (example: file1=/tmp/to ); in Asterisk 1.0.x use...

.call files Asterisk-Настройка call back для ТАКСИ

.call файлы — Текстовый файл соответствующий определенному синтаксису Синтаксис .call файлов Channel :  : Канал, который будет использоваться для исходящего вызова. CallerID: Name  CallerID, MaxRetries:  Количество попыток для неудачного вызова (не включая первую попытку, т.е. 0 = означает совершить 1 попытку вызова). Значение по умолчанию: 0. RetryTime:  Количество секунд между попытками вызова, не стоит очень часто ломиться на недоступный телефон. Значение по умолчанию: 300 (5 минут) WaitTime:  Количество секунд для ожидания ответа на вызов. Значение по умолчанию: 45. Account: Установка поля “account code”для записи в CDR. Если первый участник вызова ответил, то далее описываем с кем и как его соединить Context:  Контекст в файле extensions.conf. Extension:  Название екстеншена в extensions.conf.. Priority:  Номер приоритета для екстеншена, с которого нужно начать выполнение. Set: Установка переменных канала для использования их в логике обраб...