MikroTik с нуля 12. Два провайдера: резервирование и маршрутизация по условиям
Note
Команды сверены с официальной документацией RouterOS 7 (версия руководства 7.26). Перед работой на боевом оборудовании проверьте их на тестовом стенде или сделайте резервную копию.
Эта статья сложнее остальных в серии: здесь сходятся таблица маршрутов, NAT, firewall и маршрутизация по условиям. Она нужна не всем, и читать её подряд необязательно. Выберите свой путь:
| Что вам нужно | Что читать |
|---|---|
| Только «упал основной провайдер, интернет переключился на резервный» | «Как роутер выбирает маршрут» и часть 1: шаги 1–4 (шаг 5 по желанию) |
| Отдельные устройства всегда ходят через второго провайдера | Часть 2: шаги 6–7 (или вместо шага 7 шаг 8) |
| Сервер или VPN должен отвечать через второй канал | Часть 2: шаг 6 (создаёт таблицу to_isp2, нужную шагу 9), затем шаг 9 |
| Что-то не работает | Шаг 10 и «Типичные ошибки» |
Что получится в итоге:
- интернет работает через первого провайдера, а при его отказе роутер сам переключается на второго и возвращается обратно, когда основной канал восстановится;
- NAT и firewall одинаково защищают и обслуживают оба канала;
- выбранные устройства всегда выходят в интернет через второго провайдера;
- ответы на входящие подключения уходят тем же каналом, которым пришёл запрос;
- вы умеете проверить, куда на самом деле идёт трафик.
Что понадобится
- Роутер MikroTik с RouterOS 7, настроенный по статьям 03 и 04: мост
bridge, адрес192.168.88.1/24, списки интерфейсовLANиWAN, минимальный firewall и правило masquerade. Если вы уже выполнили статью 07, прочитайте предупреждение в шаге 1: ваши порты распределены иначе. - Два подключения к интернету. В примерах: первый провайдер на
ether1(сеть203.0.113.0/24, наш адрес203.0.113.2/30, шлюз203.0.113.1), второй наether2(сеть198.51.100.0/24, наш адрес198.51.100.2/30, шлюз198.51.100.1). Ваши реальные адреса и шлюзы возьмите из договоров или личных кабинетов провайдеров. - Компьютер, подключённый к порту, который мы не будем трогать (в этой статье это
ether3), и привычка включать Safe Mode (Ctrl+Xв терминале, кнопка Safe Mode в WinBox; подробно в статье 02). - Резервная копия конфигурации.
Как роутер выбирает маршрут
Нужно понять три понятия: таблица маршрутов, distance и scope.
Таблица маршрутов. Это список «куда отправлять пакеты». По умолчанию в RouterOS одна таблица — main. Для адреса назначения роутер сначала выбирает самый конкретный подходящий маршрут: адрес 192.0.2.80 ближе к маршруту 192.0.2.0/24, чем к маршруту по умолчанию 0.0.0.0/0. Маршрут по умолчанию подходит для всего остального.
Distance. Если до одного и того же назначения ведут несколько маршрутов, действует тот, у которого distance меньше. Остальные остаются в таблице неактивными и ждут. Это и есть основа резервирования. Для справки: у подключённых сетей distance равен 0, у статического маршрута и маршрута от DHCP-клиента по умолчанию — 1.
Warning
Если у двух маршрутов к одному назначению одинаковый distance, RouterOS объединит их в один маршрут с несколькими шлюзами (ECMP, Equal Cost Multi-Path — несколько равноценных маршрутов; флаг +) и будет распределять соединения между провайдерами по хэшу адресов. Для «основной и резервный» нужны разные значения.
Scope и target-scope. Эти два числа нужны, когда шлюз маршрута находится не в соседней сети, а «за несколькими хопами» (рекурсивная маршрутизация, она понадобится в шаге 5). scope — «уровень» самого маршрута, target-scope — максимальный уровень маршрута, через который разрешено искать его шлюз. У подключённого маршрута scope 10, у статического 30; у статического target-scope по умолчанию 10, поэтому обычный шлюз находится только через подключённую сеть. Увеличивая target-scope, мы разрешаем искать шлюз через маршруты с более высоким scope; в шаге 5 мы для этого понижаем scope у контрольных маршрутов до 10 и ставим target-scope=11.
Активность маршрута видна по флагам в /ip route print: A — активен, I — неактивен, s — статический, c — подключённая сеть, d — получен по DHCP, + — входит в ECMP.
Часть 1. Резервирование канала
Шаг 1. Освободить ether2 и настроить адреса
В заводской конфигурации ether2 входит в мост bridge. В этой статье он становится вторым WAN, поэтому LAN-порты сдвигаются: теперь это ether3–ether5 (число портов зависит от модели, см. статью 03).
Warning
Если вы сейчас подключены к роутеру через ether2, после следующей команды связь пропадёт. Переткните кабель компьютера в ether3 и включите Safe Mode до начала работы. Если к ether2 подключено ещё что-то (точка доступа, коммутатор), перенесите это на свободный порт ether3–ether5.
Important
Если вы уже выполнили статью 07. Там ether2 — порт управления (pvid=1, адрес роутера 192.168.88.1), ether3 и ether4 — access-порты VLAN 10 и 20, ether5 — trunk. Забирая ether2, вы теряете этот вход, поэтому действуйте в Safe Mode:
- подключайтесь кабелем к
ether3: это VLAN 10, роутер там отвечает по адресу192.168.10.1; - если вы вручную вносили
ether2в записи/interface bridge vlan, уберите его оттуда; - примеры этой статьи с
192.168.88.52и192.168.88.0/24относятся к сети без VLAN. Подставьте подсеть и адрес вашего устройства (например, из192.168.10.0/24), а правила-исключения для всех подсетей VLAN есть в шаге 7; - на пятипортовой модели при двух WAN остаётся три LAN-порта, и схему из статьи 07 придётся сократить.
Убираем порт из моста:
/interface bridge port remove [find where interface=ether2]
Назначаем адрес второго провайдера и добавляем порт в список WAN:
/ip address add address=198.51.100.2/30 interface=ether2
/interface list member add list=WAN interface=ether2
Если адрес первого провайдера вы ещё не задавали статически, сделайте это (при получении адреса по DHCP эту команду пропустите, см. подраздел «Если адрес получается по DHCP» в шаге 3):
/ip address add address=203.0.113.2/30 interface=ether1
Как проверить.
/interface bridge port print
/interface list member print
/ip address print
В списке портов моста не должно быть ether2. В списке WAN должны быть ether1 и ether2, в списке LAN — bridge. Адреса 203.0.113.2/30 и 198.51.100.2/30 должны стоять на своих портах и не быть помечены флагами X (отключён) или I (invalid, недействителен). Если ether2 ещё не подключён к кабелю провайдера, адрес всё равно будет показан, но маршрут к сети провайдера появится только когда линк поднимется.
Шаг 2. NAT и firewall для двух каналов
Если вы сделали всё по канону из статей 03 и 04, менять почти ничего не нужно: правило masquerade и правила firewall завязаны на списки интерфейсов, а не на конкретный порт. Посмотрите, есть ли оно:
/ip firewall nat print where action=masquerade
Должно быть правило chain=srcnat action=masquerade с out-interface-list=WAN (в нашем каноне комментарий masquerade LAN to internet, в заводской конфигурации он другой). Добавлять его повторно не нужно. Одно такое правило подменяет адрес источника на адрес того интерфейса, через который пакет реально уходит: через ether1 — на 203.0.113.2, через ether2 — на 198.51.100.2. Так же работают правила firewall с in-interface-list=WAN: они автоматически защищают и второго провайдера.
Если же ваше правило masquerade привязано к одному интерфейсу (out-interface=ether1), замените его. Команды ниже выполняйте только в этом случае: они затрагивают лишь правило, привязанное к ether1, поэтому другие masquerade-правила (например, hairpin NAT из статьи 05) останутся на месте:
/ip firewall nat remove [find where chain=srcnat and action=masquerade and out-interface=ether1]
/ip firewall nat add chain=srcnat action=masquerade out-interface-list=WAN comment="masquerade LAN to internet"
Как проверить. Выполните /ip firewall nat print и убедитесь, что есть правило masquerade с out-interface-list=WAN. Забытый NAT на втором канале — самая частая причина ситуации «переключилось, а интернета нет»: пакеты уходят к провайдеру с частным адресом источника и отбрасываются.
Шаг 3. Простое резервирование: два маршрута по умолчанию
Идея: два маршрута 0.0.0.0/0, у основного distance=1, у резервного distance=2. Пока шлюз основного отвечает, действует он. Как только перестаёт отвечать, активным становится второй.
Сначала посмотрите, что уже есть:
/ip route print where dst-address=0.0.0.0/0
Если статический маршрут по умолчанию на первого провайдера уже есть (после статьи 03), отредактируйте его:
/ip route set [find where dst-address=0.0.0.0/0 and gateway=203.0.113.1] distance=1 check-gateway=ping comment="ISP1 primary"
Если его нет, добавьте:
/ip route add dst-address=0.0.0.0/0 gateway=203.0.113.1 distance=1 check-gateway=ping comment="ISP1 primary"
И добавьте резервный маршрут:
/ip route add dst-address=0.0.0.0/0 gateway=198.51.100.1 distance=2 check-gateway=ping comment="ISP2 backup"
Параметр check-gateway=ping заставляет роутер периодически пинговать шлюз: по умолчанию раз в 10 секунд, с ожиданием ответа 1 секунду. После двух безответных проверок шлюз считается недоступным, маршрут становится неактивным, и в работу вступает следующий по distance. Когда шлюз снова ответит, маршрут возвращается. Параметры проверки меняются в /routing settings (check-gateway-ping-interval, check-gateway-ping-timeout, check-gateway-ping-count). Можно проверять и через arp (запрос соответствия IP- и MAC-адреса вместо ping) или bfd (протокол быстрой проверки связности), но новичку хватает ping.
Important
Перед включением check-gateway=ping убедитесь, что шлюз провайдера вообще отвечает на ping: /ping 203.0.113.1 count=4. Если шлюз не отвечает на ICMP (протокол, которым работает ping), роутер сочтёт канал мёртвым, хотя интернет работает.
Как проверить.
/ip route print where dst-address=0.0.0.0/0
Должно быть два маршрута. Основной (через 203.0.113.1) с флагом A (активен), резервный (через 198.51.100.1) без A: он виден в таблице, но не используется. Если оба активны и помечены +, значит, distance совпадает.
Если адрес получается по DHCP
DHCP-клиент сам добавляет маршрут по умолчанию с distance=1. Если так будут настроены оба порта, у них будет одинаковый distance и получится ECMP (см. выше). Поэтому вместо команд со статическими маршрутами разведите значения и включите проверку шлюза в самом клиенте:
/ip dhcp-client set [find where interface=ether1] default-route-distance=1 check-gateway=ping
/ip dhcp-client add interface=ether2 default-route-distance=2 check-gateway=ping
Проверка выглядит так же, как выше. Остальная часть статьи написана для статических адресов и шлюзов: команды с comment= рассчитаны именно на статические маршруты, а особенности DHCP вынесены в отдельные абзацы.
Ограничения check-gateway
Простая проверка не идеальна, и о её границах важно знать:
- Она проверяет только шлюз, то есть ближайший к вам роутер провайдера. Если неисправность дальше (обрыв магистрали, авария на стороне провайдера), шлюз продолжит отвечать, а интернета не будет. Переключения не произойдёт.
- Время переключения — десятки секунд, а не мгновение: оно задаётся интервалом, таймаутом и числом попыток проверки.
- Существующие соединения не «переезжают»: у запасного канала другой внешний адрес, поэтому они оборвутся, и приложения установят их заново. Если кабель физически вынут, роутер сам сбрасывает masquerade-соединения этого интерфейса (так сказано в документации по NAT); если канал «умер» за шлюзом, часть старых соединений может подвисать до таймаута.
- При возврате основного канала соединения, начатые через резервный, как правило, обрываются. Документация по NAT описывает и неприятный случай: пакеты старых соединений могут уйти в основной канал без маскарадинга и «утечь» в сеть провайдера с частными адресами. От этого защищает запасной маршрут
blackhole, см. «Типичные ошибки».
От первого ограничения избавляет шаг 5; время переключения он не сокращает.
Шаг 4. Проверить переключение
Проверка должна быть настоящей: резерв, который ни разу не проверяли, обычно не работает в нужный момент.
Сначала убедитесь, что до отказа всё идёт через основного провайдера. Запустите трассировку до любого доступного внешнего узла (192.0.2.80 в примере условный, подставьте реальный; это не должен быть контрольный адрес из шага 5). Нас интересует только первый хоп (первый промежуточный маршрутизатор на пути), поэтому ограничим глубину:
/tool traceroute address=192.0.2.80 count=1 max-hops=3
В первой строке результата должен быть шлюз первого провайдера 203.0.113.1. Дальнейшие строки могут быть пустыми, если адрес условный: важен именно первый хоп.
Теперь имитируйте отказ. Самый честный способ — вынуть кабель из ether1. Если физически это неудобно, отключите маршрут (так вы проверите саму смену провайдера, но не работу check-gateway):
/ip route disable [find where comment="ISP1 primary"]
Подождите несколько секунд и посмотрите таблицу:
/ip route print where dst-address=0.0.0.0/0
Активным должен стать маршрут ISP2 backup. Повторите трассировку: теперь первым хопом будет 198.51.100.1. Проверьте с компьютера в сети, что страницы открываются.
Случай «кабель на месте, а интернета у провайдера нет» вживую повторить сложнее: нужно, чтобы шлюз перестал отвечать на ping. Если возможность появится, проверьте и его: именно ради него существует check-gateway.
Верните основной канал:
/ip route enable [find where comment="ISP1 primary"]
(или воткните кабель обратно). Маршрут ISP1 primary снова станет активным, а трассировка опять пойдёт через 203.0.113.1. Если вы тестировали кабелем, на возврат уйдут те же десятки секунд, пока роутер не убедится, что шлюз отвечает.
Если адрес от провайдера получен по DHCP, у маршрута нет нашего комментария ISP1 primary. Найдите маршрут в /ip route print where dst-address=0.0.0.0/0 и отключайте и включайте его по номеру: /ip route disable <номер>, /ip route enable <номер> (либо просто вынимайте кабель).
Шаг 5 (по желанию). Улучшенная проверка: рекурсивный маршрут
Проверять доступность шлюза провайдера мало, интереснее проверять, что через провайдера достижим интернет. Для этого в RouterOS есть рекурсивные маршруты (способ описан в документации «Failover (WAN Backup)»). Схема такая:
- Выбираем для каждого провайдера по одному «контрольному» внешнему адресу, который стабильно отвечает на ping.
- Для каждого такого адреса делаем отдельный маршрут через шлюз «своего» провайдера.
- Маршруты по умолчанию делаем не на шлюзы провайдеров, а на контрольные адреса, с
check-gateway=ping.
Теперь «шлюз» маршрута по умолчанию находится в интернете, и его пингуют именно через нужного провайдера. Если до контрольного адреса нет связи, маршрут деактивируется, даже когда сам шлюз провайдера отвечает.
В примерах контрольные адреса условные: 192.0.2.90 для первого провайдера и 192.0.2.91 для второго. Подставьте реальные надёжные адреса, разные для каждого канала: к одному адресу можно вести только один маршрут.
Warning
Выполняйте этот шаг в Safe Mode, особенно при удалённом доступе. Порядок команд выбран так, чтобы у роутера всё время был маршрут по умолчанию: сначала мы добавляем новые маршруты и только потом убираем простые маршруты шага 3. Если поменять порядок, между удалением и добавлением роутер останется без выхода в интернет.
Сначала добавьте маршруты к контрольным адресам. Значение scope=10 нужно, чтобы эти маршруты можно было использовать для поиска шлюза:
/ip route add dst-address=192.0.2.90/32 gateway=203.0.113.1 scope=10 comment="check host via ISP1"
/ip route add dst-address=192.0.2.91/32 gateway=198.51.100.1 scope=10 comment="check host via ISP2"
Маршруты по умолчанию на контрольные адреса. Значение target-scope=11 разрешает искать шлюз через маршруты с scope до 11, то есть через только что созданные:
/ip route add dst-address=0.0.0.0/0 gateway=192.0.2.90 distance=1 target-scope=11 check-gateway=ping comment="ISP1 primary (recursive)"
/ip route add dst-address=0.0.0.0/0 gateway=192.0.2.91 distance=2 target-scope=11 check-gateway=ping comment="ISP2 backup (recursive)"
Теперь у каждого провайдера по два маршрута по умолчанию с одинаковым distance (простой и рекурсивный), и оба ведут через одного и того же провайдера, так что на работе это не сказывается. Уберите простые маршруты шага 3:
/ip route remove [find where comment="ISP1 primary"]
/ip route remove [find where comment="ISP2 backup"]
Команды ищут маршруты по точному совпадению комментария, поэтому рекурсивные маршруты (ISP1 primary (recursive) и т. д.) они не заденут.
Если адреса получены по DHCP, простых маршрутов с нашими комментариями нет: вместо удаления выключите у клиентов автоматический маршрут по умолчанию, иначе он останется рядом с рекурсивными и подменит проверку через контрольный адрес проверкой одного шлюза. Шлюз провайдера для команд этого шага подставьте вручную: текущее значение видно в /ip dhcp-client print detail (поле gateway).
/ip dhcp-client set [find where interface=ether1] add-default-route=no
/ip dhcp-client set [find where interface=ether2] add-default-route=no
Как проверить.
/ip route print where dst-address=0.0.0.0/0
/ip route print detail where dst-address=0.0.0.0/0
Основной маршрут должен быть активен; в подробном выводе ищите поле immediate-gw: там указан реально достижимый шлюз (203.0.113.1 с интерфейсом ether1), через который роутер разрешил контрольный адрес. Затем повторите проверку переключения из шага 4, отключив рекурсивный маршрут основного провайдера:
/ip route disable [find where comment="ISP1 primary (recursive)"]
Если вы уже добавили второй контрольный адрес (он описан ниже), второй маршрут основного провайдера удержит его активным, поэтому отключите оба маршрута сразу:
/ip route disable [find where comment~"ISP1 primary"]
Убедитесь по /ip route print where dst-address=0.0.0.0/0, что активным стал ISP2 backup (recursive), а трассировка к 192.0.2.80 идёт через 198.51.100.1. Трассировать к самому контрольному адресу для этой проверки нельзя: к нему всегда ведёт отдельный маршрут через «свой» канал. После проверки включите маршруты обратно:
/ip route enable [find where comment~"ISP1 primary"]
Что нужно знать об этом способе:
- Контрольный адрес должен отвечать на ping всегда. Если его выключат или заблокируют ICMP, ваш канал будет считаться мёртвым.
- Трафик к самому контрольному адресу всегда идёт через «свой» канал и при аварии этого канала не переключается на резерв. Поэтому не берите в качестве контрольных адреса, которые роутер или клиенты используют как DNS или для других служб: после «успешного» переключения такой сервис окажется недоступным.
- Для надёжности документация предлагает по два контрольных адреса на канал: два маршрута по умолчанию с одинаковым distance образуют ECMP, и на второго провайдера роутер переходит, только когда недоступны все контрольные адреса первого.
Для первого провайдера второй контрольный адрес добавляется так (для второго провайдера всё то же самое, но с его шлюзом и distance=2):
/ip route add dst-address=192.0.2.92/32 gateway=203.0.113.1 scope=10 comment="check host 2 via ISP1"
/ip route add dst-address=0.0.0.0/0 gateway=192.0.2.92 distance=1 target-scope=11 check-gateway=ping comment="ISP1 primary (recursive 2)"
Два маршрута с distance=1 здесь не ошибка, а задумка: оба идут через одного провайдера, и пара работает как «жив хотя бы один контрольный адрес». В /ip route print они будут помечены + (ECMP).
Tip
Если вам нужно только резервирование, на этом всё закончено: можно переходить к «Типичным ошибкам». Часть 2 нужна, когда отдельные устройства обязаны ходить через второго провайдера или когда сервисы должны отвечать через оба канала. Её можно пропустить без потери остального.
Часть 2. Маршрутизация по условиям (для продвинутых)
Здесь речь уже не о резервировании: мы будем решать, какой канал использовать, по признакам трафика (кто отправил, куда, на какой порт). Это легко отрезает доступ, поэтому читайте внимательно и работайте в Safe Mode. Нам понадобятся три понятия:
- таблица маршрутов — мы уже знаем
main, теперь добавим вторую, свою; - правило маршрутизации (
/routing rule) — «если пакет такой-то, ищи маршрут в такой-то таблице»; - mangle — раздел firewall, где пакеты и соединения получают метки. Он ничего не запрещает и не разрешает, а только «подписывает» трафик, чтобы по подписи его можно было направить в нужную таблицу.
Шаг 6. Своя таблица маршрутов
До сих пор все пользователи шли через одного провайдера, а второй был запасным. Теперь сделаем так, чтобы выбранные устройства всегда выходили через второго. Это и называется маршрутизацией по условиям (policy routing). Сначала нужна отдельная таблица.
Caution
Ошибка в правилах маршрутизации или в mangle может отрезать вас от роутера: например, если метка случайно захватит ваш собственный компьютер. Выполняйте шаги 6–9 в Safe Mode (Ctrl+X, подробности в статье 02) и выходите из него с сохранением только после проверки, что доступ к роутеру и интернет работают.
Important
В RouterOS 7 таблицу нужно создать заранее, прежде чем использовать её имя где-либо ещё. Параметр fib разрешает таблице устанавливать свои маршруты в «рабочую» таблицу пересылки. В RouterOS 6 такого шага не было.
/routing table add name=to_isp2 fib
Добавляем в неё маршрут по умолчанию через второго провайдера. Окончание @main означает «найти адрес шлюза в таблице main» (там есть подключённая сеть второго провайдера; в новой таблице её нет). Если адрес второго провайдера получен по DHCP, подставьте его текущий шлюз из /ip dhcp-client print detail (поле gateway):
/ip route add dst-address=0.0.0.0/0 gateway=198.51.100.1@main routing-table=to_isp2 check-gateway=ping comment="ISP2 for policy table"
Как проверить.
/routing table print
/ip route print where routing-table=to_isp2
В списке таблиц должна появиться to_isp2, а единственный маршрут в ней — активный маршрут по умолчанию через 198.51.100.1. Сама по себе таблица пока ничего не меняет: трафик в неё никто не направляет.
Шаг 7. Направить устройство в таблицу правилом routing rule
Самый простой способ — правила в /routing rule. Они смотрят на адрес источника, адрес назначения, входящий интерфейс и routing-mark.
Выберите устройство и закрепите за ним адрес, иначе правило «потеряет» его при смене адреса. Например, для устройства с MAC-адресом AA:BB:CC:DD:EE:FF задайте статическую аренду DHCP:
/ip dhcp-server lease add address=192.168.88.52 mac-address=AA:BB:CC:DD:EE:FF server=dhcp1 comment="device via ISP2"
Чтобы устройство в новой таблице не потеряло связь с локальной сетью, сначала добавьте правило-исключение, а затем само правило. Правила проверяются по порядку:
/routing rule add dst-address=192.168.88.0/24 action=lookup table=main comment="LAN stays in main"
/routing rule add src-address=192.168.88.52/32 action=lookup table=to_isp2 comment="device .52 via ISP2"
Первое правило нужно потому, что в таблице to_isp2 есть маршрут по умолчанию, который «подходит для всего», в том числе для адресов внутри ваших подсетей.
Если вы выполняли статью 07, нужны такие же исключения для подсетей VLAN. Добавьте их до правила устройства (если правило устройства уже создано, удалите его и создайте заново после исключений: правила проверяются в порядке создания):
/routing rule add dst-address=192.168.10.0/24 action=lookup table=main comment="VLAN 10 stays in main"
/routing rule add dst-address=192.168.20.0/24 action=lookup table=main comment="VLAN 20 stays in main"
/routing rule add dst-address=192.168.30.0/24 action=lookup table=main comment="VLAN 30 stays in main"
Tip
Есть и более общий приём. Правило /routing rule add src-address=192.168.88.52/32 action=lookup table=main min-prefix=0 ищет в main, но «прячет» маршруты с длиной префикса 0, то есть маршрут по умолчанию. Тогда любые более конкретные маршруты (внутренние подсети, VPN) продолжают работать, а всё остальное падает в следующее правило с таблицей to_isp2. Такое правило ставится вместо исключений для LAN и выше правила с table=to_isp2.
Слово lookup означает: искать в указанной таблице, а если подходящего маршрута нет, переходить к следующим правилам (в итоге к main). Отсюда поведение при аварии: если второй провайдер упал, маршрут в to_isp2 станет неактивным, и устройство уйдёт в интернет через первого. Если нужно строгое поведение («только через второго, а при его отказе — нет интернета»), замените действие на lookup-only-in-table:
/routing rule set [find where comment="device .52 via ISP2"] action=lookup-only-in-table
Выбирайте по задаче: для устройства, которому нужен именно адрес второго провайдера (например, привязка по IP на стороне партнёра), нужно строгое поведение; для обычного «разгрузим первый канал» лучше lookup.
Warning
FastTrack (правило fasttrack из статьи 04) пропускает пакеты установленных соединений мимо обычной обработки: маршрут для них ищется только в таблице main, а правила маршрутизации не применяются. Документация прямо требует не пускать через FastTrack соединения, идущие через другие таблицы, иначе пакеты уйдут по main, то есть через первого провайдера. Поэтому исключение обязательно. Мы выводим наше устройство из FastTrack: два правила принимают его пакеты до правила fasttrack. Соединения, которые устройство уже успело открыть, продолжат идти по-старому, пока не закроются, поэтому после настройки перезапустите на устройстве приложение или сетевое подключение. Если вы отключили правило fasttrack целиком (например, ради очередей в статье 09), эти два правила не нужны, но вреда от них нет.
/ip firewall filter add chain=forward action=accept connection-state=established,related src-address=192.168.88.52 place-before=[find where action=fasttrack-connection] comment="no fasttrack for device .52 (src)"
/ip firewall filter add chain=forward action=accept connection-state=established,related dst-address=192.168.88.52 place-before=[find where action=fasttrack-connection] comment="no fasttrack for device .52 (dst)"
Как проверить.
/routing rule print
В списке должны быть ваши правила в нужном порядке (исключения для LAN выше правила устройства). На самом устройстве выполните трассировку (tracert -d 192.0.2.80 в Windows, traceroute -n 192.0.2.80 в Linux): первым хопом после роутера должен быть 198.51.100.1. Если открыть на устройстве любой сервис «мой IP», он покажет адрес второго провайдера, а на остальных компьютерах — первого.
Шаг 8. Вариант через mangle и address-list
У /routing rule есть ограничение: источник задаётся адресом или подсетью, списки адресов (address-list) правило не принимает. Если устройств много, их адреса разбросаны или нужны условия вроде «только этот порт», используйте mangle с действием mark-routing. Метка маршрутизации — это имя той самой таблицы.
Caution
Не применяйте для одного и того же трафика и routing rule, и mangle. По умолчанию mangle обрабатывается раньше правил, и если помеченный трафик находит маршрут в своей таблице, правила его уже не увидят. Для одного устройства выберите один способ. Если вы пробуете этот шаг, сначала отключите правило устройства из шага 7:
/routing rule disable [find where comment="device .52 via ISP2"]
Если затем решите вернуться к варианту шага 7, включите правило обратно командой enable с тем же условием.
Списки адресов: устройства, которые идут через второго провайдера, и внутренние подсети, которые трогать нельзя:
/ip firewall address-list add list=via_isp2 address=192.168.88.52
/ip firewall address-list add list=local_nets address=192.168.88.0/24
Если вы выполняли статью 07, добавьте в local_nets и подсети VLAN:
/ip firewall address-list add list=local_nets address=192.168.10.0/24
/ip firewall address-list add list=local_nets address=192.168.20.0/24
/ip firewall address-list add list=local_nets address=192.168.30.0/24
Первое правило помечает новые соединения этих устройств в интернет. Условие dst-address-type=!local защищает сам роутер: без него помечались бы и обращения к адресам роутера, и он стал бы недоступен (это типичная ошибка, о ней говорит документация):
/ip firewall mangle add chain=prerouting action=mark-connection new-connection-mark=conn_isp2 passthrough=yes in-interface-list=LAN src-address-list=via_isp2 dst-address-list=!local_nets dst-address-type=!local connection-state=new comment="mark connections via ISP2"
Второе правило направляет все пакеты помеченных соединений в таблицу to_isp2:
/ip firewall mangle add chain=prerouting action=mark-routing new-routing-mark=to_isp2 passthrough=no in-interface-list=LAN connection-mark=conn_isp2 comment="route marked connections via ISP2"
Помеченные соединения не должны попадать в FastTrack. Самый простой способ — разрешить FastTrack только соединениям без метки (это заодно покроет и шаг 9). Правило fasttrack из канона при этом меняется:
/ip firewall filter set [find where action=fasttrack-connection] connection-mark=no-mark
Note
Это отход от канона статьи 04, и вот как он сочетается с остальным. Условие connection-mark=no-mark касается только соединений с метками, поэтому исключения для отдельных адресов из шага 7 и отключение правила fasttrack целиком (статья 09) ему не мешают: отключённое правило остаётся отключённым, а исключения просто срабатывают раньше. Чтобы вернуть правило к канону, снимите условие командой /ip firewall filter set [find where action=fasttrack-connection] !connection-mark (восклицательный знак перед именем параметра означает «сбросить значение»).
Как проверить.
/ip firewall mangle print stats
/ip firewall connection print where connection-mark=conn_isp2
Счётчики правил должны расти, когда устройство открывает сайты, а в таблице соединений должны появиться записи с меткой conn_isp2. Дальше проверяйте так же, как в конце шага 7: трассировкой с самого устройства.
Шаг 9. Ответный трафик: входящие подключения через второго провайдера
Допустим, вы публикуете сервер 192.168.88.10 (как в статье 05) по адресу второго провайдера. Запрос приходит на ether2, роутер переадресует его серверу. Но ответ сервера идёт по таблице main и по умолчанию уйдёт через ether1, с адресом источника второго провайдера. Первый провайдер такие пакеты, как правило, отбрасывает, поскольку источник не из его сети. Для клиента сервер просто «не отвечает». Это асимметричная маршрутизация: запрос пришёл по одному пути, а ответ пошёл по другому. Роутер не «помнит», откуда пришёл запрос: ответный пакет он маршрутизирует по таблице, как любой другой.
Warning
В схеме «два провайдера на одном роутере» правило drop invalid из канона (статьи 03 и 04) безопасно: роутер видит оба направления соединения. Оно мешает там, где на пути пакетов несколько роутеров и один из них видит лишь часть соединения: такие пакеты могут стать invalid. Лечится это симметричной маршрутизацией (то, что мы делаем ниже), а не ослаблением firewall.
Решение: запомнить, через какой интерфейс пришло соединение, и пускать ответы той же дорогой.
Сначала о самой публикации. Если правило проброса сделано по статье 05, с in-interface-list=WAN, оно уже принимает подключения с обоих провайдеров, и новых правил dstnat не нужно. Если оно привязано к in-interface=ether1, второй провайдер не пробрасывает ничего: замените условие на список WAN. Для опыта, если проброса пока нет, добавьте пробное правило только для второго провайдера (подробности в статье 05):
/ip firewall nat add chain=dstnat action=dst-nat in-interface=ether2 protocol=tcp dst-port=443 to-addresses=192.168.88.10 to-ports=443 comment="publish server via ISP2"
Помечаем новые соединения, пришедшие на ether2:
/ip firewall mangle add chain=prerouting action=mark-connection new-connection-mark=in_isp2 passthrough=yes in-interface=ether2 connection-state=new connection-mark=no-mark comment="mark connections arriving via ISP2"
Ответы сервера (пакеты из LAN) отправляем в таблицу to_isp2:
/ip firewall mangle add chain=prerouting action=mark-routing new-routing-mark=to_isp2 passthrough=no in-interface-list=LAN connection-mark=in_isp2 comment="replies to ISP2 connections"
Ответы самого роутера (его служб) идут в цепочке output. Для них есть два способа: правило с mangle ниже или правило /routing rule по адресу источника из шага 10. Выбирайте один:
/ip firewall mangle add chain=output action=mark-routing new-routing-mark=to_isp2 passthrough=no connection-mark=in_isp2 comment="router's own replies to ISP2 connections"
Если вы ещё не меняли правило fasttrack в шаге 8, сделайте это сейчас (это то же отступление от канона, которое описано в примечании шага 8, с тем же способом вернуть исходное состояние):
/ip firewall filter set [find where action=fasttrack-connection] connection-mark=no-mark
Для первого провайдера аналогичные правила не нужны, пока он остаётся основным: ответы и так идут в main, то есть через него. Они потребовались бы, если бы вы сделали основным второго.
Как проверить. Со стороны интернета (не из вашей сети, например с мобильного интернета) подключитесь к адресу 198.51.100.2 на порту 443; на сервере порт должен действительно слушать. Соединение должно установиться. В таблице соединений должна быть запись с меткой in_isp2, а Torch (встроенный просмотр потоков трафика на интерфейсе, подробнее в шаге 10) на ether2 покажет поток в обе стороны (и rx, и tx не нулевые):
/ip firewall connection print where connection-mark=in_isp2
/tool torch interface=ether2 port=443
Если tx в Torch равен нулю, а rx растёт, запрос доходит, а ответ уходит не по ether2: проверьте счётчики правил в /ip firewall mangle print stats и порядок правил.
WireGuard и два провайдера
Туннель из статьи 11 тоже может приходить на адрес второго провайдера: порт 13231/udp открыт правилом input для всего списка WAN, поэтому firewall менять не нужно. Но роутер отвечает по таблице main, а во встречных сообщениях (повторное «рукопожатие», проверка связи) может выбрать не тот канал. Документация описывает для этого отдельную схему, и она дополняет правило output выше. Включите у пира responder=yes (имя пира подставьте своё), чтобы роутер сам не начинал рукопожатие по неправильному каналу:
/interface wireguard peers set [find where name=phone] responder=yes
Затем запоминаем адрес, откуда пришло рукопожатие, и направляем ответы с порта 13231 через второго провайдера. Подмену адреса источника выполняет наше обычное правило masquerade для списка WAN, отдельное NAT-правило не требуется:
/ip firewall mangle add chain=prerouting action=add-src-to-address-list address-list=wg_via_isp2 address-list-timeout=1m protocol=udp dst-port=13231 in-interface=ether2 comment="track WireGuard peers on ISP2"
/ip firewall mangle add chain=output action=mark-connection new-connection-mark=wg_isp2 passthrough=yes protocol=udp src-port=13231 dst-address-list=wg_via_isp2 comment="mark WireGuard replies via ISP2"
/ip firewall mangle add chain=output action=mark-routing new-routing-mark=to_isp2 passthrough=no protocol=udp src-port=13231 connection-mark=wg_isp2 comment="route WireGuard replies via ISP2"
Туннель всегда будет подниматься по тому каналу, на который пришло рукопожатие. Если основной канал упал, клиент должен сам начать подключаться к адресу второго провайдера: у одного пира один endpoint, поэтому заведите на клиенте второй профиль (или переключайте DNS-имя, которое указано в endpoint). Автоматического переключения клиента на уровне RouterOS здесь нет.
Шаг 10. Отладка: куда идёт трафик на самом деле
Набор команд для «ничего не понятно»:
/ip route print where dst-address=0.0.0.0/0
/ip route print where routing-table=to_isp2
/routing rule print
/routing table print
/ip firewall mangle print stats
Первая команда показывает основные маршруты и их активность, вторая — маршруты своей таблицы, третья — порядок правил маршрутизации, четвёртая — список таблиц, пятая — работают ли метки (растут ли счётчики packets у mangle-правил).
Проверка второго канала с самого роутера. Трафик самого роутера по умолчанию идёт в main, поэтому трассировка с роутера проверяет основного провайдера. Чтобы проверить канал ether2, пошлите пробные пакеты с адресом источника второго провайдера и добавьте правило, которое направит такие пакеты в нужную таблицу. Для traceroute документация прямо говорит, что правила /routing rule применяются к пробам по адресу источника. Заодно это правило нужно и для служб самого роутера: его собственные пакеты с адресом второго провайдера не должны уходить через первого.
/routing rule add src-address=198.51.100.2/32 action=lookup-only-in-table table=to_isp2 comment="router own traffic from ISP2 address"
/tool traceroute address=192.0.2.80 src-address=198.51.100.2 count=1 max-hops=3
Первым хопом должен быть 198.51.100.1. Без правила пакеты с таким источником ушли бы в main, то есть к первому провайдеру, который их, скорее всего, отбросил бы. Правило строгое: если второй провайдер недоступен, собственные пакеты роутера с его адресом отбрасываются, а не идут через первого. Так и задумано: с таким источником другой канал их всё равно не пропустил бы. Если правило нужно только для проверки, удалите его после неё.
Note
У traceroute есть параметр vrf (VRF — отдельные виртуальные таблицы маршрутизации), но он принимает только VRF, а таблицу, созданную для policy routing, отвергает. Поэтому «вручную указать таблицу» в трассировке нельзя: проверяйте через адрес источника и правила.
Torch показывает потоки на выбранном интерфейсе. Он смотрит на пакеты до firewall. Запустите его на втором провайдере и фильтруйте по внешнему узлу: в Torch src-address означает дальнюю от интерфейса сторону, то есть узел в интернете.
/tool torch interface=ether2 src-address=192.0.2.80/32
Пока проверяемое устройство открывает сайты, на ether2 должны появляться потоки с нужным внешним узлом, а на ether1 с ним же быть не должно. Остановить Torch можно сочетанием Ctrl+C. Учтите: пока Torch работает, роутер отключает fast path (ускоренную обработку пакетов) и FastTrack, так что нагрузка на процессор растёт. И если проблема «пропадает» только при запущенном Torch, подозревайте FastTrack.
Типичные ошибки
- Асимметричная маршрутизация. Запрос пришёл через
ether2, а ответ ушёл черезether1. Признак: сервис, опубликованный на втором провайдере, недоступен снаружи, а в Torch наether2видны только входящие пакеты. Лечится шагом 9. Кроме того, если в/ip settingsвключёнrp-filter=strict, роутер отбрасывает пакеты, пришедшие не по «лучшему» обратному пути; при асимметрии документация советует режимloose:/ip settings set rp-filter=loose. Текущее значение видно в/ip settings print. - Забытый NAT или WAN-список.
ether2не добавлен в списокWAN, или masquerade привязан кether1. Устройства второго провайдера выходят с частными адресами и не получают ответов. Проверьте/interface list member printи/ip firewall nat print. - Одинаковый distance. Оба маршрута по умолчанию получаются активными, и соединения распределяются между каналами по хэшу вместо «основной и резервный». В
/ip route printтакие маршруты помечены+. Для DHCP-клиентов не забывайтеdefault-route-distance. - Blackhole-маршруты. Маршрут с параметром
blackholeмолча отбрасывает пакеты. Это может быть нужным инструментом: например, маршрут0.0.0.0/0сblackholeи большимdistanceв таблицеto_isp2(/ip route add dst-address=0.0.0.0/0 blackhole distance=250 routing-table=to_isp2) вместо перехода вmainсделает «строгое» поведение при падении второго провайдера. Но забытый blackhole с малымdistanceперекроет рабочие маршруты, и интернет пропадёт без видимых причин. Такой же запасной маршрут вmain(distance=250) отбросит пакеты, если пропали все обычные маршруты по умолчанию, и они не уйдут в сеть провайдера с частными адресами (см. ограниченияcheck-gatewayв шаге 3). Найти все blackhole-маршруты можно командой/ip route print where blackhole. - Метки захватили трафик самого роутера или локальной сети. Если mangle-правило с
mark-routingне исключает адреса роутера (dst-address-type=!local) и свою подсеть, обращения устройства к роутеру или к соседям по LAN отправляются в таблицу второго провайдера и теряются. Аналогично для/routing rule: без правила-исключения для LAN (dst-address=192.168.88.0/24 action=lookup table=main, стоящего выше) устройство из шага 7 не достучится до локальных узлов. Порядок правил важен: смотрите/routing rule print. - FastTrack и свои таблицы. Устройство вроде бы направлено во вторую таблицу, но часть соединений идёт через первого провайдера. Проверьте правило
fasttrack(шаги 7–9): оно должно пропускать только соединения без метки (connection-mark=no-mark) или не затрагивать нужные адреса.
Что дальше
- MikroTik с нуля 04. Firewall для начинающих — если нужно закрепить, как работают цепочки и FastTrack.
- MikroTik с нуля 05. Проброс портов и hairpin NAT — публикация серверов, которую мы использовали в шаге 9.
- MikroTik с нуля 08. Диагностика и мониторинг — как следить за состоянием каналов и получать уведомления.
- MikroTik с нуля 11. WireGuard: доступ в офис и туннель между офисами — VPN-сервис, ответы которого тоже должны идти тем каналом, что и запрос.