вторник, 5 января 2016 г.

Failover маркированных клиентов.

  Имеем роутер Mikrotik, к нему приходят два ISP и две группы пользователей - "важные" и "не очень важные" клиенты. Они разделены в разные подсети.

  • wan2 - основный канал интернета, он же является каналом по дефолту для нашего роутера. через него ходит в интернет группа пользователей "важные".
  • wan1 - резервный канал интернета, он является резервным для микротика, через него ходит в интернет группа пользователей "не очень важные".

  Задача.

  • организовать доступ к микротику одновременно и с wan2 и с wan1 из-вне;
  • организовать переключение при падении основного канала на резервный и переключение назад при восстановлении;
  • организовать переключение маркированных клиентов при падении их интернета с wan1 на wan2, при возобновлении - переключение назад.

Решение.
  Создаем маршруты, два обычных маршрута, два промаркированных. Обратите внимание на метрику, у маршрута с комментарием "wan2" она меньше - это и есть наш дефолтный маршрут. Маршруты с комментариями "wan1_mark" и "wan2_mark" - технические.
/ip route
add comment=wan1_mark distance=1 gateway=Y.Y.Y.Y routing-mark=wan1
add comment=wan2_mark distance=1 gateway=X.X.X.X routing-mark=wan2
add comment=wan2 distance=1 gateway=X.X.X.X
add comment=wan1 distance=2 gateway=Y.Y.Y.Y
  Доступ из-вне к микротику есть с wan2, так как этот интерфейс является дефолтным маршрутом. Но нам нужен доступ и с wan1 из-вне. Для этого используются правила 0 и 2. Правило 0 помечает входящие соединения с wan1, правило 2 отдает помеченные соединения в нужный маршрут. Подробнее в этой статье.
 /ip firewall mangle
 0    ;;; pometka_wan1
      chain=input action=mark-connection new-connection-mark=isp1
      passthrough=yes dst-address=Y.Y.Y.Y in-interface=ether1-wan1
      log=no log-prefix=""
 1    ;;; clienti_na_wan1
      chain=prerouting action=mark-routing new-routing-mark=wan1
      passthrough=yes src-address-list=wan1 log=no log-prefix=""
 2    ;;; otvet_wan1_v_interface_wan1
      chain=output action=mark-routing new-routing-mark=wan1 passthrough=yes
      connection-mark=isp1 log=no log-prefix="" 
   Правило 1 используется для пометки трафика клиентов "не очень важных" в маршрут с комментарием "wan1_mark". Клиенты должны быть в адрес-листе "wan1". Это можно сделать на этапе выдачи по адреса по DHCP:


  Создаем два скрипта, о первом я уже писал, подробно останавливаться не буду. Это failover для самого микротика и его "важных клиентов". При пропадании главного интернета роутер будет переключатся на резервный, с ним будут переключатся клиенты, которые используют главный маршрут. После этого будет происходить мониторинг главного канала на работоспособность, если он работоспособен - переключатся назад.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#   23q
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:local status [ip route get value-name=active [find comment=wan2]];
:local PingCount 3;
:local PingResult1;
:local PingResult2;
:local PingResult3;
# yandex dns
:local PingTarget1reserv 77.88.8.8;
:local PingTarget1serv false;
:local PingTarget1;
:set $PingTarget1 [:pick [:do {:resolve ya.ru} on-error={:set PingTarget1serv true}] 1];
# OpenDNS
:local PingTarget2reserv 208.67.222.222;
:local PingTarget2serv false;
:local PingTarget2;
:set $PingTarget2 [:pick [:do {:resolve www.ua} on-error={:set PingTarget2serv true}] 1];
# Google Public DNS
:local PingTarget3 8.8.8.8;
if ($PingTarget1serv =  true) do={:set PingResult1 [/ping $PingTarget1reserv count=$PingCount interface=ether2-wan2 routing-table=wan2]} else={:set PingResult1 [/ping $PingTarget1 count=$PingCount interface=ether2-wan2 routing-table=wan2]};
if ($PingTarget2serv =  true) do={:set PingResult2 [/ping $PingTarget2reserv count=$PingCount interface=ether2-wan2 routing-table=wan2]} else={:set PingResult2 [/ping $PingTarget2 count=$PingCount interface=ether2-wan2 routing-table=wan2]};
:set $PingResult3 [/ping $PingTarget3 count=$PingCount interface=ether2-wan2 routing-table=wan2];
:if (($PingResult1 + $PingResult2 + $PingResult3) >= (2 * $PingCount)) do={ if ($status=true) do={} else={/ip route enable [find comment=wan2]}}  else={ if ($status=true) do={/ip route disable [find comment=wan2]} else={}}

  Второй скрипт переключает наших маркированных клиентов, которые берут интернет из второго, резервного, канала роутера (wan1). При падении этого канала они должны переключится на основный канал маршрутизатора.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#   23q
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:local status [ip firewall mangle get value-name=disable [find comment=clienti_na_wan1]];
:local PingCount 3;
:local PingResult1;
:local PingResult2;
:local PingResult3;
# yandex dns
:local PingTarget1reserv 77.88.8.8;
:local PingTarget1serv false;
:local PingTarget1;
:set $PingTarget1 [:pick [:do {:resolve ya.ru} on-error={:set PingTarget1serv true}] 1];
# OpenDNS
:local PingTarget2reserv 208.67.222.222;
:local PingTarget2serv false;
:local PingTarget2;
:set $PingTarget2 [:pick [:do {:resolve www.ua} on-error={:set PingTarget2serv true}] 1];
# Google Public DNS
:local PingTarget3 8.8.8.8;
if ($PingTarget1serv =  true) do={:set PingResult1 [/ping $PingTarget1reserv count=$PingCount interface=ether1-wan1 routing-table=wan1]} else={:set PingResult1 [/ping $PingTarget1 count=$PingCount interface=ether1-wan1 routing-table=wan1]};
if ($PingTarget2serv =  true) do={:set PingResult2 [/ping $PingTarget2reserv count=$PingCount interface=ether1-wan1 routing-table=wan1]} else={:set PingResult2 [/ping $PingTarget2 count=$PingCount interface=ether1-wan1 routing-table=wan1]};
:set $PingResult3 [/ping $PingTarget3 count=$PingCount interface=ether1-wan1 routing-table=wan1];
:if (($PingResult1 + $PingResult2 + $PingResult3) >= (2 * $PingCount)) do={ if ($status=false) do={} else={/ip firewall mangle enable [find comment=clienti_na_wan1]}}  else={ if ($status=false) do={/ip firewall mangle disable [find comment=clienti_na_wan1]} else={}}
  Для начала мы получаем статус маршрута который маркирует пакеты для отправки в wan1, потом проверяем сам интерфейс wan1 на работоспособность, если он работоспособен - скрипт завершается, если он не рабочий, все клиенты переключаются на резервный канал. При возобновлении резервного канала клиенты переключаются на свой канал (wan1). Так же скрипт можно доработать, например, он может включать ограничения скорости для клиентов "не очень важных" когда они переключены на главный маршрут миркотика, что-бы они не мешали "важной" группе клиентов.
  Скрипты помещаем в scheduler:
/system scheduler
add interval=1m name=failover on-event=failover policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive start-date=\
    jan/01/1970 start-time=00:00:01
add interval=1m name=failover_wan1 on-event=failover_wan1 policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive start-date=\
    jan/01/1970 start-time=00:00:01

  Интервал 1 минута. За это время скрипт успевает пропинговать все хосты и выполнить действия.
  Обратите внимание, обязательно дата начала должна стоять  jan/01/1970. Это сделано для из-за того, что в роутере нет батарейки, и при перезагрузке время сбивается на 1970 год, если нет интернета - время не синхронизируется и задание не выполнится. Для перестраховки ставлю везде  jan/01/1970 - тогда задание выполнится в любом случае.

Подписаться на новые статьи.

7 комментариев:

  1. passthrough=yes что это означает

    ОтветитьУдалить
    Ответы
    1. Если стоит passthrough=yes это правило не будет блокировать пакеты в этой цепочке и пропустит их дальше, после маркировки заданной меткой. Свойство действительно только когда в правиле в Action стоит mark packet, mark connection или routing mark. Если стоит passthrough=no маркированные пакеты не будут проходить через следующие правила в mangle rule, которые находятся ниже нашего правила (как мы знаем там есть очередность). Например, наши помеченные пакеты мы хотим еще как-то пометить используя mark packet, mark connection или routing mark в правиле, которое находится ниже, тогда passthrough должен быть в yes. По-умолчанию passthrough=yes. На официальном форуме есть даже пример: http://forum.mikrotik.com/viewtopic.php?t=26646

      Удалить
  2. Вот я скрипт нашел он будет работать для вашей задачи ?

    :global testPrim
    :global testRez
    :global testPrimOld
    :global testRezOld
    :global sendto "admin@i.ua"

    :global yandexprim [ping 77.88.8.8 count=3 routing-table=ISP1_rout interface=ISP1]
    :global googleprim [ping 8.8.4.4 count=3 routing-table=ISP1_rout interface=ISP1]

    :global yandexrez [ping 77.88.8.8 count=3 routing-table=ISP2_rout interface=ISP2]
    :global googlerez [ping 8.8.4.4 count=3 routing-table=ISP2_rout interface=ISP2]

    if (($googleprim + $yandexprim) != 0) do={:set testPrim true} else={:set testPrim false}
    if (($googlerez + $yandexrez ) != 0) do={:set testRez true} else={:set testRez false}

    if (($testPrim = false) && ($testPrim != $testPrimOld)) do={

    /ip route disable [/ip route find comment="GW1"];
    /tool e-mail send to=$sendto subject="WARNING mikrotik!" body="Prim chanel is DOWN!!";
    /log warning "Prim chanel is DOWN!!";
    }

    if (($testPrim = true) && ($testPrim != $testPrimOld)) do={

    /ip route enable [/ip route find comment="GW1"];
    /tool e-mail send to=$sendto subject="mikrotik" body="Prim chanel is UP!";
    /log warning "Prim chanel is UP!";
    }

    if (($testRez = false) && ($testRez != $testRezOld)) do={

    /ip route disable [/ip route find comment="GW2"];
    /ip firewall mangle disable [find comment=to_ISP2];
    /tool e-mail send to=$sendto subject="WARNING mikrotik" body="Rez chanel is DOWN!!";
    /log warning "Rez chanel is DOWN!!";
    }

    if (($testRez = true) && ($testRez != $testRezOld)) do={

    /ip route enable [/ip route find comment="GW2"];
    /ip firewall mangle enable [find comment=to_ISP2];
    /tool e-mail send to=$sendto subject="mikrotik" body="Rez chanel is UP!";
    /log warning "Rez chanel is UP!";
    }

    :set testRezOld $testRez
    :set testPrimOld $testPrim

    ОтветитьУдалить
  3. Подскажите каким образом зайти по rdp к клиенту который находится в адрес листе wan1

    ОтветитьУдалить
    Ответы
    1. Если нужно зайти извне используя главный маршрут микротика(wan2):
      Маркируем входящие соединения на наш сервер рдп:
      /ip firewall mangle
      add action=mark-connection chain=prerouting dst-port=3389 in-interface=wan2 \
      new-connection-mark=1 protocol=tcp
      делаем проброс для маркированных пакетов
      /ip firewall nat
      add action=dst-nat chain=dstnat comment="Rdp" connection-mark=1 \
      dst-port=3389 in-interface=wan2 protocol=tcp to-addresses=1.1.1.1
      где 1.1.1.1 - айпи нашего сервера
      исключаем наши помеченые пакеты с маршрута wan1
      /ip firewall mangle
      add action=mark-routing chain=prerouting comment=na_wan1 connection-mark=!1 \
      new-routing-mark=velton src-address=1.1.1.1
      тут чуть не так как в статье, так как последнне правило действует для одного айпи, а не для группы, но смысл я думаю понятен.

      Удалить
  4. /ip firewall nat
    add action=dst-nat chain=dstnat dst-address=1.1.1.1 dst-port=3389 log=\
    yes log-prefix=rdp_ protocol=tcp to-addresses=\
    192.168.1.1 to-ports=3389
    add action=dst-nat chain=dstnat dst-address=2.2.2.2 dst-port=3389 log=\
    yes log-prefix=rdp_ protocol=tcp to-addresses=\
    192.168.1.1 to-ports=3389
    add action=src-nat chain=srcnat comment=to_ISP2 dst-address=192.168.1.1 \
    dst-port=3389 protocol=tcp to-addresses=192.168.1.254

    addresses=192.168.1.254-маршрутизатор,192.168.1.1-сервер
    думаю так должно работать

    ОтветитьУдалить