Статья участвует в Конкурсе статей по настройке оборудования Mikrotik с операционной системой RouterOS

Очень часто в IT-среде встречаются запросы на построение агрегации нескольких каналов связи, связанные с тем, что один ISP работает не стабильно и/или требуется получить большую пропускную способность. Мечты и совмещении этих двух факторов, как получение стабильности и одновременное увеличение пропускной способности канала за счет агрегации так и остаются мечтами, но некоторое движение в этом направлении все же можно совершить...

Предположим, как часто бывает — у вас дома подключено несколько интернет провайдеров и настроен автоматический переброс активного канала, если один из ISP вдруг перестал работать. Схема вполне жизнеспособная, но имеет один недостаток — один или более каналов остаются незадействованными. Что можно предпринять в этом случае? Учитывая, что в нашем распоряжении нет динамической маршрутизации, нам остается два варианта — статически раскидать маршруты по каналам или строить агрегацию с внешним роутером, находящимся, например у вас на работе или в дата-центре. Первый вариант сразу зачеркивает гибкость функционала резервирования, а вот о втором мы поговорим более детально.

Лично я сам являюсь приверженцем kernel-space транспорта в софт-роутерах, включая ROS, то есть драйвер должен находится в пространстве ядра (ko), что бы обеспечить наибольшую производительность. Следовательно, при выборе технологий агрегации в рамках ROS, казалось бы, мы должны рассматривать EoIP, GRE и т.д. Однако, встречаются такие случаи, когда стабильность отдельного канала начинает хромать, появляются потери. Тогда «бондинг» или «бриджинг» не могут адекватно отследить такое поведение и приходится вручную выключать временно неисправный канал, что крайне не удобно. Как можно парировать данный недостаток? Требуется ввести избыточную проверку работоспособности туннеля. И здесь нам на помощь приходит OpenVPN, щедро проверяющий свою жизнеспособность keep-alive пакетами.

Отлично!  Начнем.

Как уже говорилось ранее, нам потребуется два роутера R1 — роутер в квартире, R2 — роутер в ДЦ. В нашем примере будет существовать два ISP канала до ДЦ от роутера R1. Следовательно, начинать мы будет с самого низа IP стека, когда нам потребуется указать маршруты до R2. Само собой, для роутера R2 нам потребуется как минимум 2 публичных адреса в сети Интернет.

R2

/ip address add address=1.1.1.2/24 interface=ether1
/ip address add address=1.1.1.3/24 interface=ether1
/ip route add dst-address=0.0.0.0/0 gateway=1.1.1.1

R1

/ip route add dst-address=1.1.1.2/32 gateway=1.1.2.1
/ip route add dst-address=1.1.1.3/32 gateway=1.1.3.1

В настройках R1 у нас фигурирует два шлюза 1.1.2.1 и 1.1.3.1. Пускай, это будут шлюзы провайдеров для R1. Таким образом, мы обозначили, что до 1.1.1.2 мы идем через 1.1.2.1, а до 1.1.1.3 мы идем через 1.1.3.1.

Далее преступим к настройкам базовых туннелей OpenVPN.

R2

/ppp profile add name=light-ovpn only-one=yes use-compression=no use-encryption=no use-mpls=no
/ppp secret add local-address=1.1.4.1 name=ovpn-over-isp1 password=YOURPASS profile=light-ovpn remote-address=1.1.4.2 service=ovpn
/ppp secret add local-address=1.1.4.3 name=ovpn-over-isp2 password=YOURPASS profile=light-ovpn remote-address=1.1.4.4 service=ovpn
/interface ovpn-server server set auth="" certificate=none cipher="" default-profile=light-ovpn enabled=yes keepalive-timeout=360 mode=ethernet port=8085 require-client-certificate=no
/interface ovpn-server add name=ovpn-over-isp1 user=ovpn-over-isp1
/interface ovpn-server add name=ovpn-over-isp2 user=ovpn-over-isp2

Совсем забыл... Весомым преимуществом OpenVPN перед любым другим туннельным протоколом будет использование TCP вместо GRE и возможность использовать любой TCP порт, в нашем случае — 8085. В некоторых случаях это может дать серьезный выигрыш, когда на R1 мы можем столкнуться с NAT без поддержки GRE.
IP адреса на туннели назначаются лишь для того, что бы OpenVPN мог работать.

Приступим к настройке R1, нам потребуется зеркально отобразить все туннели в разделе клиента OpenVPN.

R1

/ppp profile add name=light-ovpn only-one=yes use-compression=no use-encryption=no use-mpls=no
/interface ovpn-client add add-default-route=no auth=none certificate=none cipher=none connect-to=1.1.1.2 max-mtu=1500 mode=ethernet name=ovpn-over-isp1 password=YOURPASS port=8085 profile=light-ovpn user=ovpn-over-isp1
/interface ovpn-client add add-default-route=no auth=none certificate=none cipher=none connect-to=1.1.1.3 max-mtu=1500 mode=ethernet name=ovpn-over-isp2 password=YOURPASS port=8085 profile=light-ovpn user=ovpn-over-isp2

Отлично! Туннели подняты, их состояние можно отследить в соответствующих разделах, пришло время агрегации.
Создавая эту схему у себя дома, я долго размышлял — нужна ли мне агрегация в виде эквивалентной нагрузки на всех операторов или мне будет достаточно включить требуемые каналы в бридж и развести соответствующим образом веса и path-cost. Однако, опробовав полноценную агрегацию на OpenVPN я остался доволен результатом и предлагаю свою схему в этой статье.

R1/R2

/interface bonding add link-monitoring=none mode=balance-rr mtu=1500 name=BOND-OVPN primary=none slaves=ovpn-over-isp1,ovpn-over-isp2

В данном примере мы создали интерфейс, объединяющий несколько каналов  ovpn-over-isp1 и  ovpn-over-isp2 по принципу RoundRobin (balance-rr). Это означает, что каждый пакет, поступающий в интерфейс BOND-OVPN будет идти сначала в ovpn-over-isp1, а затем в ovpn-over-isp2, равномерно загружая оба канала.

Великолепно! Мы, практически у цели... Осталось совсем немного.

Не стоит забывать, что на каналах ISP1 и ISP2 могут наблюдаться разные задержки в прохождении пакетов, а следовательно для чувствительных к реордингу протоколов могут наступить неблагоприятные времена.

Мы можем завершить наш процесс сборки туннелей созданием одного дополнительного туннеля в режиме TCP, работающего поверх BOND-OVPN.

R1

/ip address add address=1.1.5.2/30 interface=BOND-OVPN

R2

/ip address add address=1.1.5.1/30 interface=BOND-OVPN

R2

/ppp secret add local-address=1.1.6.1 name=ovpn-mainchannel password=YOURPASS profile=light-ovpn remote-address=1.1.6.2 service=ovpn
/interface ovpn-server add name=ovpn-mainchannel user=ovpn-mainchannel

R1

/interface ovpn-client add add-default-route=no auth=none certificate=none cipher=none connect-to=1.1.5.1 max-mtu=1500 mode=ethernet name=ovpn-mainchannel password=YOURPASS port=8085 profile=light-ovpn user=ovpn-mainchannel

Следует отметить, что если вы планируете передавать из ДЦ мультисервисные услуги, например multicast и IP, то ovpn-mainchannel можно разделить с помощью VLAN, например:

R1/R2

/interface vlan add interface=ovpn-mainchannel name=MainChannel-Internet vlan-id=2
/interface vlan add interface=ovpn-mainchannel name=MainChannel-IPTV vlan-id=3

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

R2

/ip address add address=1.1.7.1/30 interface=MainChannel-Internet
/ip address add address=1.1.8.1/30 interface=MainChannel-IPTV
/ip route add dst-address=1.1.1.4/32 gateway=1.1.7.2


В этом случае мы ведем на R1 IP, предоставляемый нам ДЦ1.1.1.4.

R1

/ip address add address=1.1.7.2/30 interface=MainChannel-Internet
/ip address add address=1.1.8.2/30 interface=MainChannel-IPTV
/interface bridge add name=Loopback admin-mac=00:11:22:33:44:55 auto-mac=no
/ip address add address=1.1.1.4/32 interface=Loopback
/ip route add dst-address=0.0.0.0/0 gateway=1.1.7.1 pref-src=1.1.1.4
/ip firewall nat add action=src-nat chain=srcnat out-interface=Loopback src-address=192.168.0.0/16 to-addresses=1.1.1.4

Здесь мы «приземляем» полученный нами IP на созданный Loopback из бриджа и запускаем NAT на указанный IP.

Ремарка: в правиле /ip firewall nat add action=src-nat chain=srcnat out-interface=Loopback src-address=192.168.0.0/16 to-addresses=1.1.1.4 , значение
out-interface может быть разным в зависимости от версии ROS (iptables). Это может быть Loopback на старых версиях ROS (5.x) и может быть MainChannel-Internet на новых версиях ROS (6.x).

Ну уж и коли мы заговорили о IPTV...

R1

/routing igmp-proxy interface add alternative-subnets=0.0.0.0/0 interface=MainChannel-IPTV upstream=yes
/routing igmp-proxy interface add interface=ether2

R2

/routing igmp-proxy interface add alternative-subnets=0.0.0.0/0 interface=ether2 upstream=yes
/routing igmp-proxy interface add interface=MainChannel-IPTV

Заключение

Конечно, созданная схема ни в коей мере не претендует на Enterprise решения, однако в домашних условиях, когда простой не допустим, она зарекомендовала себя великолепно. Также, долгое время я пытался решить вопрос с резервированием по средствам EoIP туннелей, объединенных в Bridge, но это не давало требуемой стабильности. Наступали моменты, когда в сети одного из операторов возникали «дропы» величиной 10-15%, что сводило с ума бридж. И тогда единственным решением казался OpenVPN. Правда, стоит отметить, что на момент написания статьи у EoIP уже также появился keep-alive, но я настолько привык к обозначенной схеме из-за утилизации TCP и возможности смены рабочего порта, что вряд ли перейду обратно на EoIP. Тем более, что в моем случае на старом Intel Atom удалось получить около 210 Mbit/s симплексного трафика, что, как я считаю, является неплохим достижением.

Участник конкурса Александр

Просьба всем кто читает статьи, участвующие в конкурсе, ставить оценки.