MikroTik (RouterOS 7) — маркировка и балансировка

В этой статье мы разберёмся с темой «Балансировка трафика» на роутере MikroTik, под управлением RouterOS 7.

Введение

В этой статье я покажу как разделить трафик на 2 провайдера с использованием роутера MikroTik и RouterOS 7.

Балансировка на роутерах MikroTik заключается в маркировке некоторого траффика, который затем помещают в разные таблицы маршрутизации. А уже в разных таблицах маршрутизации создают разные дефолтные маршруты, через разных провайдеров.

Вся настройка роутера MikroTik, в этой статье, делается с помощью команд, в которых используются шаблоны:

  • <ip-isp> — ip-адрес из сети провайдера, который вы используете на роутере.
  • <ip-local> — ip-адрес на роутере из локальной сети.
  • <local-net> — подсеть вашей локальной сети.
  • <net-isp> — выделенная вам подсеть провайдера. Если у вас 1 ip-адрес, то подсеть будет /30. А если 5, то /29.
  • <ip-gw-isp> — ip-адрес шлюза провайдера.
  • <local-ip-serv> — ip-адрес какого-нибудь сервера в локалке.

Адресация

Во-первых, если это ещё не сделано, настроим ip-адреса на роутере. Укажем 3 адреса: в локальной сети, в сети первого провайдера и в сети второго:

/ip address
add address=<ip-isp1> interface=ether1
add address=<ip-isp2> interface=ether2
add address=<ip-local> interface=ether3

Таблицы маршрутизации

Создадим две таблицы маршрутизации для двух провайдеров. Эти таблицы должны быть помечены как fib (Forwarding Information Base).

/routing table
add fib name=ISP-1
add fib name=ISP-2

Про FIB можете почитать здесь.

Дефолтные маршруты

Создаём дефолтные маршруты в таблицах маршрутизации:

/ip route
add dst-address=0.0.0.0/0 gateway=<ip-gw-isp1>
add dst-address=0.0.0.0/0 gateway=<ip-gw-isp1> routing-table=isp-1
add dst-address=0.0.0.0/0 gateway=<ip-gw-isp2> routing-table=isp-2

Обратите внимание, если мы не указываем таблицу маршрутизации, то роут попадает в таблицу main. В нашем случае в таблице main будет дефолтный маршрут через первого провайдера.

Входящий трафик

К входящим подключениям можно отнести:

  • Управление роутером, например подключение с помощью WinBox или SSH.
  • Входящие подключения VPN, когда ваш роутер выступает в роли сервера VPN.
  • Входящие подключения к сервисам на роутере, например DNS или NTP.

В этом случае балансировка будет обеспечиваться за счет подключений к роутеру MikroTik через разных провайдеров. Основной задачей здесь будет обеспечение ответа с того же интерфейса, на который пришёл запрос. Запрос может прийти как из сети первого или второго провайдера, так и из локальной сети.

Входящий трафик к роутеру

Для локальной сети всё просто, вы указали ip-адрес для локальной сети, при этом создался коннект маршрут в таблице main. То-есть компьютеры из локальной сети к роутеру будут ходить по таблице main. Мы не будем специально отлавливать такой траффик, и помещать его в другую таблицу маршрутизации.

Но входящие подключения от разных провайдеров нужно разделить, поместив их в свои таблицы маршрутизации. Входящий запрос который пришёл на Ether1 или Ether2 вначале попадёт в Connection Tracker, и там будет создано соединение. Это соединение можно промаркировать в Mangle Prerouting. Затем запрос пойдет на Routing Decision, если этот запрос предназначен не маршрутизатору, то он попадёт в таблицу Forward, а если маршрутизатору то в таблицу Input (в нашем случае).

И так, промаркируем соединения (mark-connection). Кстати, нет смысла маркировать каждый пакет, достаточно только первого в рамках соединения (connection-state=new).

/ip firewall mangle
add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=new dst-address=<net-isp1> \
    in-interface=ether1 new-connection-mark=isp-1 passthrough=no
add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=new dst-address=<net-isp2> \
    in-interface=ether2 new-connection-mark=isp-2 passthrough=no

Ответ роутера тоже пойдёт через Connection Tracker, и там он уже будет промаркирован. На основе этой марки (connection-mark) в цепочке Output (перед самым выходом) мы поместим ответ в нужную таблицу маршрутизации (mark-routing). А уже по этой таблице маршрутизации роутер найдёт интерфейс, куда послать ответ на запрос.

/ip firewall mangle
add action=mark-routing chain=output connection-mark=isp-1 new-routing-mark=isp-1 passthrough=no
add action=mark-routing chain=output connection-mark=isp-2 new-routing-mark=isp-2 passthrough=no

Трафик из интернета в локалку (NAT)

Здесь нужно пометить трафик идущий из интернета в локальную сеть через проброшенные порты. Нужно чтобы запрос пришедший через первого провайдера, ушёл тоже через первого. А запрос, пришедший через второго провайдера, ушёл через второго.

трафик из интернета в локалку (NAT)

Прокинем порты, через оба провайдера. В примере я прокидываю 80 порт.

/ip firewall nat
add action=dst-nat chain=dstnat dst-address=<ip-isp1> dst-port=80 protocol=tcp to-addresses=<local-ip-serv>
add action=dst-nat chain=dstnat dst-address=<ip-isp2> dst-port=80 protocol=tcp to-addresses=<local-ip-serv>

У нас уже существует маркировка соединения, которое мы делали для входящего трафика, его мы и будем использовать.

А помещать трафик в нужную таблицу маршрутизации, будем в таблице prerouting. Дополнительно сузим условие, что трафик идёт из локальной сети, ведь это уже ответ сервера из локальной сети.

/ip firewall mangle
add action=mark-routing chain=prerouting connection-mark=isp-1 in-interface=ether3 new-routing-mark=isp-1 passthrough=no
add action=mark-routing chain=prerouting connection-mark=isp-2 in-interface=ether3 new-routing-mark=isp-2 passthrough=no

Трафик от роутера

К исходящему трафику от самого роутера можно отнести:

  • Подключение к NTP, DNS и другим подобным сервисам с самого роутера.
  • Исходящие подключения к VPN серверам.

Это уже не ответы на запросы, это уже запросы, которые генерирует сам роутер.

Здесь мы будем использовать список сетей BOGON — это немаршрутизируемые адреса. То есть !BOGON — это интернет.

/ip firewall address-list
add address=0.0.0.0/8 list=BOGONS
add address=10.0.0.0/8 list=BOGONS
add address=100.64.0.0/10 list=BOGONS
add address=127.0.0.0/8 list=BOGONS
add address=169.254.0.0/16 list=BOGONS
add address=172.16.0.0/12 list=BOGONS
add address=192.0.0.0/24 list=BOGONS
add address=192.0.2.0/24 list=BOGONS
add address=192.168.0.0/16 list=BOGONS
add address=198.18.0.0/15 list=BOGONS
add address=198.51.100.0/24 list=BOGONS
add address=203.0.113.0/24 list=BOGONS
add address=224.0.0.0/4 list=BOGONS

Промаркируем соединения (mark-connection), который идёт от самого роутера в интернет (!BOGON). При этом, если исходящий адрес у нас относится к первому провайдеру, то он получит марку isp-1-out. А если ко второму провайдеру, то марку isp-2-out. Маркировать роуты мы будем в этой же цепочке (output), поэтому здесь дополнительно нужно указать настройку passthrough=yes.

/ip firewall mangle
add action=mark-connection chain=output connection-mark=no-mark connection-state=new dst-address-list=!BOGONS \
    new-connection-mark=isp-1-out passthrough=yes src-address=<net-isp1>
add action=mark-connection chain=output connection-mark=no-mark connection-state=new dst-address-list=!BOGONS \
    new-connection-mark=isp-2-out passthrough=yes src-address=<net-isp2>

Теперь, основываясь на промаркированных соединениях, нужно поместить трафик в нужные таблицы маршрутизации (mark-routing):

add action=mark-routing chain=output connection-mark=isp-1-out new-routing-mark=isp-1 passthrough=no
add action=mark-routing chain=output connection-mark=isp-2-out new-routing-mark=isp-2 passthrough=no

Перечисленные правила будут работать, когда мы можем указать src-address, его можно указать в утилитах tool/ping, tool/traceroute. А также в VPN клиентах l2tp, ip-ip и gre.

Если же исходящий адрес мы не можем указать, то такой трафик попадёт в таблицу main. И исходящий интерфейс будет выбран по таблице main. В моём случае трафик с роутера пойдет через первого провайдера.

Трафик от роутера

Трафик из локалки в интернет

Для балансировки такого трафика я буду использовать Per Connection Classifier. То есть, балансировка выхода в интернет через MikroTik будет автоматической.

Per Connection Classifier — берёт соединение и основываясь на портах и адресах источника и назначения создаёт хэш. Затем этот хеш делится на какой-то знаменатель (он берётся по числу провайдеров), и высчитывается остаток от деления. Фишка в том что, если мы делим хеш на 2, то в остатке может быть 0 или 1. Если делим на 3, то в остатке 0, 1 или 2.

Если у нас 2 провайдера, то хеш делим на 2, получаем в остатке:

  • 0 — трафик пускаем через 1 провайдера.
  • 1 — трафик пускаем через 2 провайдера.

Подробнее про Per Connection Classifier можете почитать здесь.

Трафик из локалки в интернет

Для начала создадим два правила srcnat, чтобы при выходе через разных провайдеров мы получали разные ip-адреса.

/ip firewall nat
add action=src-nat chain=srcnat out-interface=ether-1 src-address=<local-net> to-addresses=<ip-isp1>
add action=src-nat chain=srcnat out-interface=ether-2 src-address=<local-net> to-addresses=<ip-isp2>

Промаркируем соединения (mark-connection), которые идут из локальной сети в интернет (!BOGONS). При маркировке добавим условие per-connection-classifier. И так как, потом, роуты маркировать будем в этой же цепочке (prerouting), то добавляем правило passthrough=yes. Трафик будем маркировать следующими марками: isp-1-l и isp-2-l.

/ip firewall mangle
add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=new \ 
    dst-address-list=!BOGONS in-interface=ether-3 new-connection-mark=isp-1-l passthrough=yes \
    per-connection-classifier=src-address-and-port:2/0 src-address=<local-net>
add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=new \ 
    dst-address-list=!BOGONS in-interface=ether-3 new-connection-mark=isp-2-l passthrough=yes \ 
    per-connection-classifier=src-address-and-port:2/1 src-address=<local-net>

Поместим трафик в нужные таблицы маршрутизации в цепочке prerouting:

/ip firewall mangle
add action=mark-routing chain=prerouting connection-mark=isp-1-l new-routing-mark=isp-1 passthrough=no
add action=mark-routing chain=prerouting connection-mark=isp-2-l new-routing-mark=isp-2 passthrough=no

Итог

После таких настроек у вас будет 4 типа трафика:

  • Трафик к роутеру.
    • Запрос из локальной сети, ответ уйдёт на интерфейс локальной сети (таблица main).
    • Запрос пришёл через провайдера 1, ответ уйдёт через провайдера 1.
    • Запрос пришёл через провайдера 2, ответ уйдёт через провайдера 2.
  • Трафик из интернета к локалке через проброшенные порты.
    • Пакет пришёл через провайдера 1, прошёл NAT, попал серверу. Ответ с сервера пойдёт через провайдера 1.
    • Пакет пришёл через провайдера 2, прошёл NAT, попал серверу. Ответ с сервера пойдёт через провайдера 2.
  • Трафик от роутера.
    • Если мы можем указать src-address, то идём через определённого провайдера.
    • Если не можем указать src-address, то идём через того провайдера, дефолтный роут на кого мы указали в таблице main.
  • Трафик из локальной сети в интернет.
    • С помощью Per Connection Classifier делим весь трафик на два, половину пускаем через 1 провайдера, половину через 2 провайдера.

Итоговая табличка правил Mangle на MikroTik чтобы работала балансировка, у меня получилась такая:


Остальные мои статьи по роутерам MikroTik вы найдёте здесь.

Если понравилась статья, подпишись на мой канал в VK.

3 комментария к “MikroTik (RouterOS 7) — маркировка и балансировка”

  1. Читается легко, но при попытке повторить становится тяжко… » — выделенная вам подсеть провайдера» — какая нафиг подсеть провайдера, у нас выход в интернет. Может нужно без маски?
    «add action=mark-routing chain=output connection-mark=isp-1 new-routing-mark=isp-1 passthrough=no» — одна и та же таблица для маркировки? Нет так не получится.
    Я плохо разбираюсь, могу повторить? пытаюсь разобраться, тут же всё нужное, но не полностью показано. Хотя бы объяснили, пояснили. Или это ваша шпаргалка или хотя бы напишите пару строк для понимая.
    Спасибо за итоговый скрин, пытаюсь повторить и не сдохнуть.

    Ответить
    • А если вам провайдер подсеть выдаёт. Например выдали вам 5 айпишек, у вас будет маска /29.
      У вас условие chain=output connection-mark=isp-1 (если марка соединения isp-1 в цепочке output), и действие — маркируем роут (new-routing-mark=isp-1).
      Как будет время, наверное дополню статью теорией и объяснениями. Сейчас она коротенькая, как шпаргалка.

      Ответить

Оставьте комментарий