В этой статье мы разберёмся с темой «Балансировка трафика» на роутере MikroTik, под управлением RouterOS 7.
Введение
Эта статья основана на этом видео. Но вместо RouterOS 6 мы будем используем RouterOS 7. А для выхода клиентов из локальной сети в интернет, вместо ручной балансировки и ECMP, будем используем Per Connection Classifier.
В этой статье не будет описано резервирование, чтобы сделать её более короткой. Немного о резервировании вы можете почитать здесь — Рекурсивная маршрутизация на MikroTik. Также, в этой статье нет ничего про настройку фаервола. Здесь мы занимаемся исключительно балансировкой.
Вся настройка роутера MikroTik, в статье, делается с помощью команд. В этих командах в таких скобках < > даны шаблонны, то есть здесь вы должны указать свои данные:
- <ip-isp> — ip-адрес из сети провайдера, который вы используете на роутере.
- <ip-local> — ip-адрес на роутере из локальной сети.
- <net-isp> — выделенная вам подсеть провайдера. Если у вас 1 ip-адрес, то подсеть будет /30. А если 5, то /29.
- <ip-gw-isp> — 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
Наши таблицы маршрутизации должны смотреть только в себя:
/routing rule add action=lookup-only-in-table routing-mark=ISP-1 table=ISP-1 add action=lookup-only-in-table routing-mark=ISP-2 table=ISP-2
Создаём дефолтные маршруты в своих таблицах маршрутизации:
/ip route 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
Входящие подключения к маршрутизатору
К входящим подключениям можно отнести:
- Управление роутером, например подключение с помощью WinBox или SSH.
- Входящие подключения VPN, когда ваш роутер выступает в роли сервера VPN.
- Входящие подключения к сервисам на роутере, например DNS или NTP.
Основной задачей здесь будет обеспечение ответа с того же интерфейса, на который пришёл запрос.
Для локальной сети всё просто, вы указали ip-адрес для локальной сети, при этом создался коннект маршрут в таблице main. Но вот входящие подключения от провайдеров нужно разделить, поместив их в свои таблицы маршрутизации.
Входящий запрос из Ether1 или Ether2 попадёт вначале в Connection Tracker, там будет создано соединение. Дальше это соединение можно промаркировать в Mangle Prerouting. Затем запрос пойдет на Routing Decision, если запрос нужно маршрутизировать, то он попадёт в Forward, а если не нужно то в Input (в нашем случае).
Ответ роутера тоже пойдёт через Connection Tracker, и там он уже будет с нужно маркой (соединения). На основе этой марки в цепочке Output (перед выходом) мы поместим ответ в нужную таблицу маршрутизации. А уже по этой таблице роутер пример решение в какой интерфейс отдать ответ.
Нет смысла маркировать каждый пакет, маркируем только первый (новый) в рамках соединения. И так, маркируем соединения:
/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
Маркируем роуты в цепочке output:
/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
Исходящие подключения с маршрутизатора
К исходящим подключениям можно отнести:
- Подключение к NTP, DNS и другим подобным сервисам с самого роутера.
- Исходящие подключения к VPN серверам.
Здесь мы будем использовать список сетей 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
Будем использовать уже существующие таблицы маршрутизации ISP-1 и ISP-2. Промаркируем роуты:
/ip firewall mangle add action=mark-routing chain=output dst-address-list=!BOGONS new-routing-mark=ISP-1 passthrough=no src-address=<net-isp1> add action=mark-routing chain=output dst-address-list=!BOGONS new-routing-mark=ISP-2 passthrough=no src-address=<net-isp2>
То есть, если адрес назначения у нас внешний (!BOGONS), и исходящий адрес из сети первого провайдера то помещаем в таблицу маршрутизации ISP-1. А, если из сети второго провайдера то в таблицу маршрутизации ISP-2.
Но этого не достаточно. Выше мы сделали так, если исходящий адрес из сети первого провайдера то направляем трафик к нему. А если исходящий адрес второго провайдера, то направляем второму провайдеру. Но какой адрес выберет маршрутизатор? Маршрутизатор вберет тот, который будет указан в таблице main. А в этой таблице у нас пока нет дефолтного маршрута, создадим его.
/ip route add distance=1 dst-address=0.0.0.0/0 gateway=<ip-gw-isp1> pref-src=<ip-isp1> routing-table=main
Теперь исходящий с роутера пакет (у которого не прописан src-address) пойдет через isp-1, здесь никакой балансировки не будет.
Доступ за 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>
У нас уже существует промаркированное соединение, которое мы делали для входящих подключений к роутеру. Но нам нужно исключить интерфейс провайдера при маркировке роута.
/ip firewall mangle add action=mark-routing chain=prerouting connection-mark=ISP-1 in-interface=!ether1 new-routing-mark=ISP-1 passthrough=no add action=mark-routing chain=prerouting connection-mark=ISP-2 in-interface=!ether2 new-routing-mark=ISP-2 passthrough=no
То есть, соединение промаркировано маркой ISP-1, а интерфейс входящий не ISP-1. Значит это ответный пакет от сервера и мы должны его отправить через ISP-1. Всё тоже самое для ISP-2.
Доступ из локалки в интернет
Здесь я буду использовать балансировку Per Connection Classifier.
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 connection-mark=ISP-1 src-address=<local-net> to-addresses=<ip-isp1> add action=src-nat chain=srcnat connection-mark=ISP-2 src-address=<local-net> to-addresses=<ip-isp2>
Промаркируем соединения, которые идут из локальной сети (BOGONS) в не локальную сеть (!BOGONS).
/ip firewall mangle add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=new dst-address-list=!BOGONS \ new-connection-mark=ISP-1 passthrough=no per-connection-classifier=src-address-and-port:2/0 src-address-list=BOGONS add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=new dst-address-list=!BOGONS \ new-connection-mark=ISP-2 passthrough=no per-connection-classifier=src-address-and-port:2/1 src-address-list=BOGONS
И в цепочке Output промаркируем маршруты:
/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
После таких настроек у вас будет работать 4 типа трафика.
- Трафик к роутеру.
- Пакет пришёл из локальной сети, ответ уйдёт на интерфейс локальной сети (таблица main).
- Пришёл от провайдера, ответ уйдёт тому же провайдеру.
- Трафик от роутера.
- Всегда идёт через 1 провайдера.
- Трафик из интернета через nat к локалке.
- Пакет пришёл от провайдера, ушёл на сервер. Ответ с сервера пойдёт через того-же провайдера.
- Трафик из локалки в интернет.
- С помощью Per Connection Classifier делим весь трафик на два, половину пускаем через 1 провайдера, половину через 2 провайдера.