Последнее время стали часто спрашивать про балансировку или переключение каналов, поэтому думаю стоит поделиться своим решением по переключению на резервный канал. Местных и залетных бывалых прошу меня не пинать, знаю что не очень элегантно, даже знаю некоторые конкретные места, но как говорится, чем богаты... А если вдруг кто-то укажет на то, что можно поправить и сделать все симпатичней и самое главное покажет как, то как минимум буду безгранично благодарен!
И так, что ниже? А ниже плод моего желания отказоустойчивого интернета.
Что у меня было? Один микротик, уже полностью настроенный и работающий и 2 конца витухи от разных провайдеров. Основной провайдер отдавался по PPPoE (будет упоминаться и именоваться как isp1), запасной по DHCP (будет упоминаться как isp2). isp1 воткнут в ether3 (но это вроде не пригодится), isp2 в ether2.
Опустим настройку самих интерфейсов для подключения в соответствии с выданными провайдером настройками, она есть в тонне других мануалов. Но отдельно отмечу, что при настройке клиентов избавляемся от опции "add default route", точнее выставляем ее в положение "no" на обоих интерфейсах, включение этой опции противопоказано, так как нам нужны созданные вручную маршруты, которые будут редактироваться скриптами, с автоматически созданными маршрутами это невозможно.
Избавляемся от имеющихся основных маршрутов, если они есть.
Создаем их снова, но уже руками и добавляем к ним каменты, это важно, дальше на основе этих каментов будут отрабатывать скрипты и команды.
Код: Выделить всё
/ip route add comment=GW1 distance=1 gateway=isp1
/ip route add comment=GW2 disabled=yes distance=2 gateway=1.1.1.1
Т. к. PPPoE в моем случае основной канал, я даю ему минимально возможный distance, а маршруту резервного канала указываю больший, этим мы подстрахуемся если по каким-то причинам оба маршрута окажутся включенными при рабочем основном канале. Для упрощения и сокращения кол-ва скриптов, в маршруте с pppoe клиентом указываем само pppoe соединения, микротик это нормально проглатывает, по крайней мере на момент написания в актуальных прошивках так было. "gateway=" для dhcp клиента можно указывать вообще любой адрес, скоро его подставит скрипт, но лучше подсмотреть сразу что выдал провайдер и подставить правильным.
Т.к. второй провайдер отдается по dhcp, создадим скрипт по проверке и замене гетвея в маршруте резервного канала и назовем его check_isp2_gw.
Код: Выделить всё
:local isp2gw [ip dhcp-client get [/ip dhcp-client find interface=ether2] gateway];
:local isp2gwstat [ip route get [/ip route find comment="GW2"] gateway];
#:log info ("$isp2gw")
#:log info ("$isp2gwstat")
:if ($isp2gw != $isp2gwstat) do={ip route set [/ip route find comment="GW2"] gateway=$isp2gw; :log info ("Update ISP2 GW complete")}
Если на предыдущем шаге вы поленились указать актуальный гетвей, то можно уже запустить скрипт и он все поправит
Теперь запихнем в шедулер выполнение этого срипта, частоту выполнения указываем по вкусу, я выставил 30 сек.
Код: Выделить всё
/system scheduler add interval=30s name=check_isp2_GW on-event="/system script run check_isp2_gw" policy= ftp,reboot,read,write,policy,test,password,sniff,sensitive start-date=jan/01/1970 start-time=00:00:00
Дальше в принципе все просто, можно взять нетвоч, указать например 8.8.8.8 для проверки доступен ли интернет и там дописать пару строк на подъем и выключения нужных маршрутов в зависимости от состояния первого провайдера, даже письма несчастья оттуда можно рассылать. Но у нетвоча есть одна беда, он отправляет всего один пакет и если этот бедолага пакет вдруг заблудится по пути, нас ждет не очень приятная ситуация, нетвоч переключит маршрут, а потом тут же переключит обратно и так по кругу... Поэтому, со временем пришлось сочинять свой нетвоч
, с блэк-джеком и..., чем мы и займемся ниже.
И так, для верности хорошо бы пинговать хотя бы пару хостов и хотя бы по два каунта, 1 из 4х точно долетит, если все хорошо.
Так что создаем еще два скрипта. Первый (назовем его check_isp1_down) пингует два хоста...
Код: Выделить всё
:local PingCount 2;
:local One 8.8.8.8;
:local Too 8.8.4.4;
:local ResultOne [/ping count=$PingCount $One];
:local ResultToo [/ping count=$PingCount $Too];
:if ($ResultOne=0 && $ResultToo=0) do={/system script run isp1_down}
и если все плохо, он запускает другой скрипт (isp1_down)...
Код: Выделить всё
/system scheduler enable check_isp1_up
/system scheduler disable check_isp1_down
/ip route set [find comment="GW1"] disabled=yes
/ip route set [find comment="GW2"] disabled=no
/ip firewall connection remove [find]
Начнем с конца - видим строчку /ip firewall connection remove [find], эта прелесть шинкует все активные соединения, нужна она что бы облегчить нам жизни после переключения, что бы все не тупило, пока соединения не порвутся сами. А начинается все с непонятных строк, которых у нас еще нет (у вас нет, а у меня уже давно есть
). Это два шедулера - первый запускает уже имеющийся у нас скрипт check_isp1_down каждые 20 с., а второй будет запускать еще не существующих скрипт check_isp1_up. Создадим их и сразу все станет ясно
Первый шедулер (назовем его как и скрипт который он будет запускать check_isp1_down), который запускает наш скрипт check_isp1_down каждые 20 сек, время опять таки, по вкусу.
Код: Выделить всё
/system scheduler add interval=20s name=check_isp1_down on-event="/system script run check_isp1_down" policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon start-date=jan/01/1970 start-time=00:00:00
Второй (назовем check_isp1_up)
Код: Выделить всё
/system scheduler add disabled=yes interval=20s name=check_isp1_up on-event="/system script run check_isp1_up" policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon start-date=jan/01/1970 start-time=00:00:10
Обращаем внимание на то, что запуск второго шедулера смещен на 10 секунд, относительно первого, делал для того, что бы оба этих товарища не отработали одновременно, если вдруг они оба окажутся включенными. И самое главное, видим что этот шедулер во первых выключен, а во вторых запускает скрипт которого у нас нет, так что создадим его (назовем его check_isp1_up).
Код: Выделить всё
:local PingCount 2;
:local One 8.8.8.8;
:local Too 8.8.4.4;
:local ResultOne [/ping count=$PingCount $One];
:local ResultToo [/ping count=$PingCount $Too];
:if ($ResultOne>0 || $ResultToo>0) do={/system script run isp1_up}
Как видно, это чудо тоже пингует те же два хоста по два каунта, но в случае если ответил хотя бы один пинг, выполняет другое действие - запускает еще один скрипт, создадим и его (назовем isp1_up)
Код: Выделить всё
/system scheduler disable check_isp1_up
/system scheduler enable check_isp1_down
/ip route set [find comment="GW1"] disabled=no
/ip route set [find comment="GW2"] disabled=yes
/ip firewall connection remove [find]
И вот теперь, когда все перед глазами, расскажу как это работает - шедулер check_isp1_down каждые 20 сек запускает скрипт check_isp1_down, если все хорошо и хотя бы один пинг пролез, то не происходит ничего, если выпали все 4 пинга, то запускается скрипт isp1_down, который во первых выключает первый шедулер (check_isp1_down) и включает второй шедулер check_isp1_up, а во вторых выключает основной маршрут первого провайдера с каментом GW1 и включает второго GW2, плюс до кучи рвет все соединения.
Что происходит дальше, а дальше чудеса, второй шедулер (check_isp1_up) каждые 20 секунд пингует те же 2 хоста и хосты ему тут же отвечают! Да, да, через второго провайдера интернет-то появился и тут же происходит обратное переключение на неработающий линк, но нам же нужен интернет, а не бесконечные переключения туда сюда, поэтому ваяем костыль, да простят меня бывалые и завсегдатые!
Костыль будет в виде фаервольных запретов на пинги до этих хостов через второго провайдера
Код: Выделить всё
/ip firewall filter add action=drop chain=output dst-address=8.8.8.8 out-interface=ether2 protocol=icmp
/ip firewall filter add action=drop chain=output dst-address=8.8.4.4 out-interface=ether2 protocol=icmp
А до кучи полечим еще одну болячку и сделаем еще один костыль...
Код: Выделить всё
/ip route add distance=1 dst-address=8.8.4.4/32 gateway=isp1
/ip route add distance=1 dst-address=8.8.8.8/32 gateway=isp1
Причины его наличия я точно описать не могу, может бывалые помогут, но суть такова, бывало такое, что после возвращения интернета в основном канале пинги упорно пытались уйти через резервный, а там наш фаервольный запрет, соответственно тик упорно думал что интернета в основном канале так и нет и не переключался обратно, а эти маршруты лечат эту болячку.
И так болячки полечили, костылей навтыкали, возвращаемся к тому, что произошло после выключения основного провайдера - включился второй шедулер check_isp1_up и каждые 20 секунд он запускает скрипт check_isp1_up, тот в свою очередь пингует хосты, пока лежит основной канал пинги не пройдут, их не пустит фаервол, но как только основной канал подымется, скрипт check_isp1_up запустит другой скрипт - isp1_up, который вернет все обратно - выключит маршрут резервного канал, включит основного, выключит второй шедулер check_isp1_up и включит первый check_isp1_down и опять разорвет нам все соединения, что бы мы не мучилась в ожиданиях. Ну и на этом все =)