Балансировка трафика в Mikrotik между двумя WAN-интерфейсами с учетом входящего трафика

в 14:58, , рубрики: mikrotik, Сетевое оборудование, Сетевые технологии, метки:

Недавно решил попробовать реализовать простую балансировку трафика между несколькими WAN. Почему именно простую? Я слишком тяжело разбираюсь в больших массивах информации, и подозреваю не один я. Поэтому решил попробовать разработать схему в которой разберется даже новичок, так как мало использовать чужие наработки, нужно знать что и для чего ты делаешь.

Сразу предупреждаю – система имеет много недостатков, например возможны обращения к одному и тому же ресурсу с разных IP, что чревато слетом авторизации. Так что использовать ее лучше всего для подключений которые не чувствительны к source address, тем же торентам например.

И еще, я не буду описывать настройку Микротика с нуля, предполагается что у вас уже есть роутер с двумя ВАНами, на котором заведены уже IP-адреса, локальные порты так же настроенные. И что пользователь боле-менее ориентируется в микротике, хотя бы на уровне того что знает где-какой пункт меню находится.

Для совсем новичков и людей слабо разбирающихся в сетях(можно быть мастером в одном и новичком в другом, ничего необычного в таком не вижу) я разместил пару спойлеров
Итак. Условно примем что:
— локальные адреса у нас лежат в диапазоне 192.168.0.0/16 и подключены к бриджу Localca
— Провайдер1 сидит у нас на интерфейсе WAN1, с шлюзом 10.0.0.1
— Провайдер2 сидит у нас на интерфейсе WAN2, с шлюзом 172.16.25.1

Итак приступим.

Первым делом создадим новые маршруты:

/ip route
add disabled=no distance=1 dst-address=192.168.0.0/16 gateway=Localca routing-mark=isp2 scope=30 target-scope=10
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=172.16.25.1 routing-mark=isp2 scope=30 target-scope=10
add disabled=no distance=1 dst-address=192.168.0.0/16 gateway=Localca routing-mark=isp1 scope=30 target-scope=10
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=10.0.0.1 routing-mark=isp1 scope=30 target-scope=10

Что такое роуты, они же маршруты

Маршруты это указание роутеру на каком порту или за каким IP-адресом искать нужную подсеть. Без этого роутер не будет знать куда отсылать пакеты. Вот поэтому мы и указали не только шлюзы для интернета но и порт на котором находятся наши локальные адреса

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

Cоздадим мангл который будет все новые коннекты отправлять на нужный шлюз:

/ip firewall mangle
add action=mark-connection chain=prerouting connection-mark=no-mark disabled=no dst-address=!192.168.0.0/16 new-connection-mark=inet_con passthrough=yes
add action=mark-routing chain=prerouting comment=multiwan  connection-mark=inet_con disabled=no new-routing-mark=isp2 passthrough=no

Первое правило ловит все не промаркированные (а значит новые) коннекты которые идут не в нашу локалку, а следовательно пойдут через WAN интерфейс, и маркирует их нужной меткой. Я выбрал такой подход, так как ВАН интерфейсов у нас несколько, и для каждого пришлось бы создавать отдельное правило с нужным Out. Interface, а так мы ограничились одним правилом. Второе правило коннектам с нужной меткой назначает марк роутинга. Comment служит нам для того что бы мы могли найти это правило скриптом.

mark-routing, для чего он

Марк роутинга служит для указания таблицы маршрутизации выбранным пакетам/соединениям. Они будут использовать только те роуты которые несут соответствующий Routing Mark. Таким методом мы можем разный трафик отправлять на разные шлюзы/порты по нужных нам условиях. Все что левее закладки Action в манглах(да и в фильтре и NAT) это фильтр. Так что чем меньше мы критериев укажем тем шире будет охват подпадающего под это правило трафика. Соответственно комбинируя разные условия мы очень точно может отделить нужный нам трафик.

Следующим пунктом мы идем в System-Scripts и создаем новый скрипт вот такого вот содержания:

:global rx1 "0"
:global rx2 "0"
/interface monitor WAN1 once do={ 
   :global rx1 $("rx-bits-per-second"); 
} 
/interface monitor WAN2 once do={ 
   :global rx2 $("rx-bits-per-second"); 
} 
:local one 20000000
:local two 8000000
:global wan1  ($one / $rx1)
:global wan2 ($two / $rx2)
if ($wan1>$wan2) do={/ip firewall mangle set [find comment=multiwan] new-routing-mark=isp1} else={/ip firewall mangle set [find comment=multiwan] new-routing-mark=isp2}

Сначала мы обнуляем переменные, потом получаем в эти переменные данные о загруженности интерфейсов(а конкретно то количество получаемых бит в секунду, за что отвечает параметр rx-bits-per-second). Дальше в переменные one и two вписываем ширину каждого интернет-канала в битах, и получаем обратную(так как микротик не показывает дробную часто то при делении количества бит на ширину мы бы получили 0) относительную загруженность(делим ширину на загруженность в битах). А потом их сравниваем, и если число больше у первого ВАНа то в наш мангл(здесь и пригодился комментарий, по нему мы и обратились к нужному манглу) вписываем роутмарк для ВАН1, иначе к ВАН2.
Теперь дело за малым – задать периодичность исполнения скрипта. Идем в System-Sheduler и добавляем новую задачу с нужным интервалом исполнения, в поле on Event: вписываем

/system script run erazel_balancing

Где erazel_balancing – это имя скрипта в котором мы меняем мангл. Не забудьте поменять на имя вашего скрипта.
Вот теперь мы имеем полностью автоматическую систему балансировки нагрузки на внешние интерфейсы в зависимости от их относительной загруженности.

Ну и остается еще вопрос обращения к серверу с разных внешних адресов. Так что я бы советовал данный подход применять для торентов и других не критично-важных приложений. Просто в первом мангле(который маркирует конекшны ) сделать еще условие по протоколу и порту, ну и продублировать его для разных протоколов/портов. Например:

add action=mark-connection chain=prerouting connection-mark=no-mark disabled=yes dst-address=!192.168.0.0/16 new-connection-mark=inet_con passthrough=yes protocol=tcp src-port=45000

Автор: erazel

Источник


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js