// DevOps

MikroTik: возврат трафика через тот же шлюз, которым он пришёл

Опубликовано 24.06.2026

Есть роутер MikroTik, он смотрит в интернет через WAN1. Пока шлюз один — всё работает. Стоит появиться второму WAN, VPN-туннелю с BGP-маршрутами или просто специфичным /32-префиксам в таблице main — начинается классика: запрос пришёл через WAN1, а ответ уходит через WAN2 или VPN. Клиент видит RST или ждёт таймаута.

Клиент → [WAN1] → MikroTik --dstnat--> 192.168.1.10
Клиент ← [WAN2] ← MikroTik <-----------  ответ

Это асимметричная маршрутизация. Она проявляется в двух разных сценариях, и каждый требует своего подхода.


Почему RouterOS так делает

Когда нужно отправить пакет, RouterOS смотрит в таблицу маршрутизации main и выбирает лучший маршрут до адреса назначения. Если в main несколько дефолтных маршрутов или BGP нагнал туда своих префиксов — роутер вполне законно выберет другой интерфейс. Он не обязан «помнить», откуда пришёл исходный запрос. Это нормальное поведение L3-маршрутизатора, которое в данном случае мешает.


Два сценария

Сценарий 1 — port forwarding (dstnat). Запрос с WAN1 форвардируется на внутренний сервер через dstnat. Ответ сервера уходит обратно через роутер, и роутер выбирает интерфейс по таблице main. Если там есть специфичный маршрут до адреса источника — ответ уйдёт не туда.

Сценарий 2 — прямые подключения к роутеру. SSH, ICMP, API, Winbox — всё, что адресовано самому роутеру. Запрос пришёл через WAN1, роутер генерирует ответ и снова смотрит в main. BGP-маршрут для адреса источника есть — ответ уходит через VPN или WAN2.

Оба сценария решаются через одну изолированную таблицу маршрутизации, но mangle-правила для них разные.


Подготовка: отдельная таблица маршрутизации

Создаём изолированную таблицу с единственным маршрутом — дефолт через WAN1:

routeros
/routing table add name=via-wan1 fib

/ip route add \
    dst-address=0.0.0.0/0 \
    gateway=<WAN1_GATEWAY> \
    routing-table=via-wan1

Всё. Больше в эту таблицу ничего добавлять не нужно.


Правила mangle

Нужны четыре правила. Важен порядок — они должны идти именно в такой последовательности.

Правило 1 — пометить dstnat-соединения

Срабатывает на входе через WAN1 только на пакеты, прошедшие через dstnat. Ставит метку на всё соединение целиком:

routeros
/ip firewall mangle add \
    chain=prerouting \
    in-interface=<WAN1_INTERFACE> \
    connection-nat-state=dstnat \
    action=mark-connection \
    new-connection-mark=from-wan1-dstnat \
    passthrough=yes \
    comment="Mark dstnat connections from WAN1"

Правило 2 — routing-mark для dstnat-соединений

Ловит все пакеты помеченного dstnat-соединения, включая ответные с LAN, и проставляет им routing-mark:

routeros
/ip firewall mangle add \
    chain=prerouting \
    connection-mark=from-wan1-dstnat \
    action=mark-routing \
    new-routing-mark=via-wan1 \
    passthrough=no \
    comment="Route dstnat replies back via WAN1"

Правило 3 — пометить прямые подключения к роутеру

Те же условия, что в правиле 1, но для не-dstnat-трафика — SSH, ICMP и всё остальное, что идёт напрямую к роутеру:

routeros
/ip firewall mangle add \
    chain=prerouting \
    in-interface=<WAN1_INTERFACE> \
    connection-nat-state=!dstnat \
    action=mark-connection \
    new-connection-mark=from-wan1 \
    passthrough=yes \
    comment="Mark non-dstnat connections from WAN1"

Правило 4 — routing-mark для ответов роутера

И вот здесь критически важная деталь: цепочка output, не prerouting.

routeros
/ip firewall mangle add \
    chain=output \
    connection-mark=from-wan1 \
    action=mark-routing \
    new-routing-mark=via-wan1 \
    passthrough=no \
    comment="Route router replies to WAN1 connections via WAN1"

Почему правило 4 в output, а не в prerouting

Это главная ловушка. Первый инстинкт — поставить mark-routing в prerouting по аналогии с правилом 2. Выглядит логично, но ломает роутер.

mark-routing в prerouting влияет на решение о маршрутизации для текущего пакета. Для форвардируемых пакетов (которые идут через роутер транзитом) это работает корректно. Но для пакетов, адресованных самому роутеру, RouterOS применяет этот routing-mark тоже. Роутер ищет свой собственный адрес (94.102.124.79) в таблице via-wan1, находит только дефолт 0.0.0.0/0 → <WAN1_GATEWAY> и пытается форвардить пакет к вышестоящему шлюзу вместо того, чтобы принять его локально. SSH падает мгновенно, роутер становится недоступен.

# Как выглядит ошибка:
# Входящий SSH-пакет → mark-connection from-wan1 → mark-routing via-wan1 →
# RouterOS ищет 94.102.124.79 в via-wan1 →
# находит только 0.0.0.0/0 → gateway →
# форвардит к провайдеру вместо локальной обработки →
# соединение падает

output chain обрабатывает только пакеты, которые сам роутер генерирует в ответ. Именно здесь нужно ставить routing-mark — когда роутер уже принял пакет и формирует ответ.


Как это работает внутри

dstnat-соединение (port forwarding):

  1. Пакет входит через WAN1
  2. Connection tracking видит, что соединение пройдёт через dstnat
  3. Правило 1: connection-mark=from-wan1-dstnat
  4. Правило 2: routing-mark=via-wan1
  5. dstnat меняет dst-адрес на 192.168.1.10
  6. Сервер получает запрос, формирует ответ
  7. Ответ входит через LAN-интерфейс → prerouting
  8. Правило 2 снова срабатывает по метке соединения → routing-mark=via-wan1
  9. Ответ уходит через WAN1

Прямое подключение к роутеру (SSH, ping):

  1. Пакет входит через WAN1
  2. Правило 3: connection-mark=from-wan1
  3. Роутер принимает пакет (input chain)
  4. Роутер генерирует ответ (output chain)
  5. Правило 4: routing-mark=via-wan1
  6. Ответ уходит через WAN1, минуя любые специфичные маршруты в main

На что обратить внимание

Fasttrack. Если настроен fasttrack (connection-state=established,related), он обходит mangle для установленных соединений. В типовых конфигурациях fasttrack включён по умолчанию. Правило с passthrough=no должно стоять раньше fasttrack, иначе соединения после handshake будут проскакивать мимо.

BGP. В BGP-окружениях проблема проявляется острее всего — BGP может нагнать тысячи специфичных префиксов, и для любого из них таблица main выберет не тот интерфейс. Изолированная таблица via-wan1 на это не реагирует — там только дефолт.

Несколько WAN. Схема масштабируется: для WAN2 создаёте таблицу via-wan2, дефолт через второй шлюз, и четыре аналогичных правила. Таблицы не мешают друг другу.


Проверка

Счётчики правил в mangle — видно, что правила реально срабатывают:

routeros
/ip firewall mangle print stats

Активные соединения с нужными метками:

routeros
/ip firewall connection print where connection-mark=from-wan1-dstnat
/ip firewall connection print where connection-mark=from-wan1

Маршрут в изолированной таблице:

routeros
/ip route print where routing-table=via-wan1

Итог

ПравилоЦепочкаЧто делает
mark-connection (dstnat)preroutingПомечает port-forwarded соединения с WAN1
mark-routing (dstnat)preroutingНаправляет ответы dstnat через via-wan1
mark-connection (!dstnat)preroutingПомечает прямые подключения к роутеру с WAN1
mark-routing (!dstnat)outputНаправляет ответы роутера через via-wan1

Таблица маршрутизации одна на оба сценария. Правила для dstnat и прямых подключений работают независимо, не мешая друг другу и не затрагивая остальной трафик.

// Reviews

Отзывы по теме

ladohinpy

Mikrotik hap настройка роутера. Настрою роутер микротик wifi для вас

21.07.2025 · ★ 5/5

Отличный специалист, шарящий эксперт и замечательный человек. За час нам починил то, над чем мы днями ломали головы! Уверен, что это не первый раз, когда мы будем пользоваться его непомерным профессионализмом

Отличный специалист, шарящий эксперт и замечательный человек. За час нам починил то, над чем мы днями ломали головы! Уверен, что это не первый раз, когда мы будем пользоваться его непомерным профессионализмом

Ravenor

Mikrotik hap настройка роутера. Настрою роутер микротик wifi для вас

28.05.2025 · ★ 5/5

Спасибо! Настроили роутер по моему техническому заданию, с полным объяснением того что мы делаем

Спасибо! Настроили роутер по моему техническому заданию, с полным объяснением того что мы делаем

GFSoft

Mikrotik hap настройка роутера. Настрою роутер микротик wifi для вас

09.03.2025 · ★ 5/5

Опытный покупатель

// Contact

Нужна помощь?

Свяжись со мной и я помогу решить проблему

Написать в Telegram

Отвечаю в течение рабочего дня (03:00–13:00 GMT)

Или оставьте заявку здесь:

Написать и получить быстрый ответ