Пользователь
0,0
рейтинг
16 августа 2013 в 18:58

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

Недавно решил попробовать реализовать простую балансировку трафика между несколькими 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
карма
7,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (14)

  • +1
    Интересная конструкция, но слишком тяжёлая. я бы лучше посмотрел в сторону ECMP тем более вы делаете практически тоже самое.
    http://wiki.mikrotik.com/wiki/ECMP_load_balancing_with_masquerade
    • 0
      Да, там всё проще, но учитываеться только количество соединений, а хотелось работать с загруженостью канала в битах. Ну и еще момент такой что если каналы уж очень разные по ширине то замучимся в дефолтный роут вписывать шлюзы, например когда соотношение 3:7.
      Ну и немаловажным было желание сделать что-то новое.
      • 0
        ваша конструкция имеет право на жизнь, только при условии если интерфейсы не Full Duplex
        • 0
          а если full то работать не будет?
          Можно пояснить почему?
    • 0
      Альтернатива ECMP, у которого может возникнуть проблема с динаминческим роутингом или сменой маршрутов которую нужно делать статически:

      PCC, How PCC Works
      ECMP: Known Issues
      • 0
        С динамическими проще простого — ip route set [find comment=«222»] gateway=[/ip route get [find comment=«111»] gateway] — Этот скрипт вешаем в планировщик. Если роут динамический то меняем [find comment=«111»] на number=X. Ну и имеем в нашем маршруте шлюз из динамического. Теперь мы можем ссылаться на наш статический маршрут, а он всегда будет иметь шлюз взятый из динамического. Да, конструкция немного сложноватая, но избавляет от проблем с невозможностью изменения роут-марка для динамического роута. Кстати, в РСС мы опять же ссылаемся на роутмарки, и динамический роут нам подсунет свинью.
        Если где ошибся в ращетах то буду рад подсказке где именно.
        • 0
          Жаль, что это невозможно использовать с dhcp-client-ом в смысле он не поддерживает comment. Так бы можно было использовать динамическим ip в моем случае.
  • +1
    Ставлю плюс за реализацию
    только переименуйте заголовок, так как входящий трафик балансировать нельзя. и вы работаете с исходящим трафиком prerouting
    image
    • 0
      Если подскажите подходящее название то буду благодарен.
      По сути да, мы с исходящим трафиком работаем, но сама суть идеи — отправлять запросы на входящий трафик в нужный ВАН-интерфейс. Грубо говоря указываем куда бы роутер хотел принимать входящий трафик в даный момент времени. Вот поэтому я и позволил себе такую вольность в названии.
      • 0
        «Балансировка канала, с учётом входящего трафика» как нибудь так
        Я бы в вашем случае извратился с loopback и сделал «NAT один к одному» и тогда мы можем контролировать входящий трафик на loopback
        • 0
          А поподробней о идее можна?
    • 0
      Вы не могли бы подсказать, где хорошо объяснена предложенная Вами илюстрация. А то как раз не могу разобратся с бриджем. Благодарю.
  • 0
    в микротике нет интерфейса loopback можно сделать пустой бридж, даёте ip адрес, на него nat 1-to-1 в этом случае у вас будет исходящий трафик на интерфейс loopback вот его можете краить как хотите, можете очереди навесить, а по факту будет тот же трафик что и на wan интерфейс
  • 0
    У меня вопрос, что произойдет если один wan отвалиться?

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.