Mangle на MikroTik — маркировка и приоритизация пакетов
Mangle на MikroTik — маркировка пакетов и соединений
Mangle — таблица firewall, предназначенная для маркировки трафика. В отличие от filter (разрешить/запретить) и NAT (трансляция адресов), Mangle не блокирует и не изменяет пакеты, а ставит на них невидимые "метки". Эти метки затем используются в других частях RouterOS: очереди (Queue) используют packet-mark для приоритизации, маршруты используют routing-mark для policy-based routing, а connection-mark связывает все пакеты одного соединения. Mangle — ключевое звено между классификацией трафика и действиями над ним.
Описание
Зачем нужен Mangle
Mangle решает задачу: "как указать RouterOS, что делать с конкретным видом трафика, не блокируя его". Типичные сценарии:
- QoS (Quality of Service) — пометить VoIP-трафик для приоритизации в очередях
- Policy-Based Routing — направить трафик определённых пользователей через конкретного провайдера
- Load Balancing (PCC) — распределить соединения между двумя каналами
- Учёт трафика — подсчитать объём трафика по категориям
- DSCP/TOS — изменить поле DSCP в заголовке пакета для QoS на L3-уровне
Цепочки (Chains)
Mangle работает в пяти цепочках, каждая из которых обрабатывает пакеты на определённом этапе прохождения через роутер:
| Chain | Когда срабатывает | Типичное применение |
|---|---|---|
| prerouting | До принятия решения о маршрутизации | Routing-mark для PBR, mark-connection входящего трафика |
| input | Пакет предназначен самому роутеру | Маркировка трафика к сервисам роутера (DNS, VPN) |
| forward | Пакет проходит транзитом через роутер | Маркировка клиентского трафика для QoS |
| output | Пакет исходит от самого роутера | Маркировка трафика, генерируемого роутером |
| postrouting | После принятия решения о маршрутизации | Финальная маркировка, DSCP, изменение TTL |
Важно: routing-mark работает только в prerouting и output, потому что маршрутизация выполняется после prerouting (для транзитного трафика) и в output (для трафика от роутера).
Типы маркировок
RouterOS использует три типа маркировок:
Connection-mark — метка на уровне соединения. Ставится один раз на первый пакет, затем автоматически применяется ко всем последующим пакетам этого соединения (включая ответные). Это экономит ресурсы CPU, так как классификация происходит только один раз.
Packet-mark — метка на каждый отдельный пакет. Используется в Queue Tree для приоритизации. Packet-mark можно ставить на основе connection-mark, что создаёт двухшаговую схему: сначала маркируем соединение, затем на его основе маркируем пакеты.
Routing-mark — метка, определяющая таблицу маршрутизации. Пакет с routing-mark ищет маршрут не в основной таблице (main), а в указанной. Основа policy-based routing и PCC load balancing.
Passthrough
Параметр passthrough определяет, продолжит ли пакет проверяться следующими правилами mangle после текущего совпадения:
- passthrough=yes (по умолчанию) — пакет продолжает движение по цепочке правил. Используется в первом шаге (mark-connection), чтобы следующее правило могло на основе connection-mark поставить packet-mark
- passthrough=no — обработка прекращается. Используется в финальном правиле маркировки для экономии CPU
Настройка
Двухшаговая маркировка (connection + packet)
Стандартный подход — сначала маркируем соединение, затем на его основе маркируем пакеты. Это эффективнее, чем маркировать каждый пакет по полному набору критериев:
[admin@MikroTik] ># Шаг 1: маркируем соединение (passthrough=yes — идём дальше) /ip/firewall/mangle/add chain=forward \ src-address=192.168.88.0/24 \ connection-state=new \ action=mark-connection new-connection-mark=LAN-traffic \ passthrough=yes comment="Шаг 1: mark connection LAN" # Шаг 2: на основе connection-mark ставим packet-mark /ip/firewall/mangle/add chain=forward \ connection-mark=LAN-traffic \ action=mark-packet new-packet-mark=LAN-packets \ passthrough=no comment="Шаг 2: mark packets LAN"
Маркировка VoIP-трафика для QoS
Приоритизация VoIP — классический пример использования Mangle. SIP-сигнализация идёт на порт 5060, а RTP-голос — на портах 10000-20000 (зависит от АТС):
[admin@MikroTik] ># Маркируем SIP-соединения /ip/firewall/mangle/add chain=forward \ protocol=udp dst-port=5060-5061 \ connection-state=new \ action=mark-connection new-connection-mark=voip-conn \ passthrough=yes comment="VoIP SIP connection" # Маркируем RTP-соединения /ip/firewall/mangle/add chain=forward \ protocol=udp dst-port=10000-20000 \ connection-state=new \ action=mark-connection new-connection-mark=voip-conn \ passthrough=yes comment="VoIP RTP connection" # Маркируем пакеты VoIP для Queue Tree /ip/firewall/mangle/add chain=forward \ connection-mark=voip-conn \ action=mark-packet new-packet-mark=voip-pkt \ passthrough=no comment="VoIP packets for QoS"
Затем в Queue Tree эти пакеты получают максимальный приоритет:
[admin@MikroTik] >/queue/tree/add name="VoIP-priority" parent=global \ packet-mark=voip-pkt priority=1 max-limit=2M \ comment="VoIP — максимальный приоритет"
Установка DSCP для QoS на L3
DSCP (Differentiated Services Code Point) позволяет передать приоритет трафика upstream-оборудованию. Полезно, когда MikroTik отдаёт трафик на управляемый коммутатор или провайдеру с поддержкой QoS:
[admin@MikroTik] ># Установить DSCP EF (Expedited Forwarding, 46) для VoIP /ip/firewall/mangle/add chain=postrouting \ connection-mark=voip-conn \ action=change-dscp new-dscp=46 \ passthrough=no comment="DSCP EF для VoIP" # DSCP AF21 (18) для бизнес-трафика /ip/firewall/mangle/add chain=postrouting \ connection-mark=business-conn \ action=change-dscp new-dscp=18 \ passthrough=no comment="DSCP AF21 для бизнес-приложений"
Policy-Based Routing — направление трафика через конкретного провайдера
Сценарий: трафик гостевой сети (192.168.20.0/24) отправляем через ISP2, остальной — через ISP1:
[admin@MikroTik] ># Создаём routing table /routing/table/add name=to-ISP2 fib # Default route для таблицы ISP2 /ip/route/add dst-address=0.0.0.0/0 gateway=198.51.100.1 \ routing-table=to-ISP2 comment="ISP2 gateway" # Маркируем трафик гостевой сети /ip/firewall/mangle/add chain=prerouting \ src-address=192.168.20.0/24 \ dst-address-type=!local \ action=mark-routing new-routing-mark=to-ISP2 \ passthrough=no comment="Гостевая сеть через ISP2"
Важно: dst-address-type=!local исключает трафик, предназначенный самому роутеру (DNS-запросы, доступ к WebFig). Без этого условия даже обращения к роутеру будут маршрутизироваться через ISP2.
PCC Load Balancing (Per Connection Classifier)
PCC распределяет соединения между двумя провайдерами на основе хеша адресов/портов:
[admin@MikroTik] ># Routing tables /routing/table/add name=to-ISP1 fib /routing/table/add name=to-ISP2 fib # Маршруты по умолчанию для каждой таблицы /ip/route/add dst-address=0.0.0.0/0 gateway=203.0.113.1 \ routing-table=to-ISP1 /ip/route/add dst-address=0.0.0.0/0 gateway=198.51.100.1 \ routing-table=to-ISP2 # Маркировка соединений для PCC (50/50) /ip/firewall/mangle/add chain=prerouting \ in-interface=bridge-LAN \ connection-state=new \ dst-address-type=!local \ per-connection-classifier=both-addresses:2/0 \ action=mark-connection new-connection-mark=ISP1-conn \ passthrough=yes comment="PCC: 50% через ISP1" /ip/firewall/mangle/add chain=prerouting \ in-interface=bridge-LAN \ connection-state=new \ dst-address-type=!local \ per-connection-classifier=both-addresses:2/1 \ action=mark-connection new-connection-mark=ISP2-conn \ passthrough=yes comment="PCC: 50% через ISP2" # Routing mark на основе connection-mark /ip/firewall/mangle/add chain=prerouting \ connection-mark=ISP1-conn \ in-interface=bridge-LAN \ action=mark-routing new-routing-mark=to-ISP1 \ passthrough=no comment="Route ISP1 connections" /ip/firewall/mangle/add chain=prerouting \ connection-mark=ISP2-conn \ in-interface=bridge-LAN \ action=mark-routing new-routing-mark=to-ISP2 \ passthrough=no comment="Route ISP2 connections"
per-connection-classifier=both-addresses:2/0 означает: разделить на 2 группы по хешу src+dst address, взять группу 0. Это гарантирует, что одно и то же соединение всегда идёт через одного провайдера.
Маркировка по address-list
Маркировка трафика к определённым сайтам или сервисам через address-list:
[admin@MikroTik] ># Address-list с адресами видеоконференций /ip/firewall/address-list/add list=video-services address=meet.google.com /ip/firewall/address-list/add list=video-services address=zoom.us # Маркировка соединений к видеосервисам /ip/firewall/mangle/add chain=forward \ dst-address-list=video-services \ connection-state=new \ action=mark-connection new-connection-mark=video-conn \ passthrough=yes comment="Video conferencing connections" /ip/firewall/mangle/add chain=forward \ connection-mark=video-conn \ action=mark-packet new-packet-mark=video-pkt \ passthrough=no comment="Video conferencing packets"
Разделение download и upload
Для Queue Tree часто нужно отдельно маркировать upload и download:
[admin@MikroTik] ># Upload (из LAN наружу) /ip/firewall/mangle/add chain=prerouting \ in-interface=bridge-LAN \ action=mark-packet new-packet-mark=upload \ passthrough=no comment="Upload traffic" # Download (извне в LAN) /ip/firewall/mangle/add chain=postrouting \ out-interface=bridge-LAN \ action=mark-packet new-packet-mark=download \ passthrough=no comment="Download traffic"
Проверка
Просмотр правил Mangle
[admin@MikroTik] ># Все правила mangle с счётчиками /ip/firewall/mangle/print stats # Подробная информация /ip/firewall/mangle/print detail # Только правила для конкретной цепочки /ip/firewall/mangle/print where chain=forward
Проверка маркировок на трафике
[admin@MikroTik] ># Сбросить счётчики и проверить, растут ли они /ip/firewall/mangle/reset-counters-all # Через несколько секунд проверяем /ip/firewall/mangle/print stats
Если счётчики (bytes, packets) растут — правило срабатывает. Если нет — проверьте критерии матчинга.
Проверка connection-mark
[admin@MikroTik] ># Посмотреть активные соединения и их метки /ip/firewall/connection/print where connection-mark=voip-conn
Проверка routing-mark
[admin@MikroTik] ># Маршруты в конкретной routing table /ip/route/print where routing-table=to-ISP2 # Проверка, что маркированный трафик идёт через правильный gateway /tool/traceroute address=8.8.8.8 routing-table=to-ISP2
Типичные ошибки
-
Passthrough=no на connection-mark — если поставить passthrough=no на правиле mark-connection, следующее правило (mark-packet) никогда не сработает для первого пакета соединения. Правило mark-connection почти всегда должно иметь passthrough=yes
-
Routing-mark не в prerouting — routing-mark работает только в цепочках prerouting (для транзитного трафика) и output (для трафика от роутера). Правило mark-routing в chain=forward будет проигнорировано, потому что решение о маршрутизации уже принято
-
Забыли connection-state=new — маркировка соединений должна применяться только к новым соединениям (connection-state=new). Без этого условия правило будет пытаться повторно маркировать каждый пакет уже маркированного соединения, что создаёт лишнюю нагрузку
-
Нет routing table для routing-mark — маркировали трафик routing-mark=ISP2, но не создали routing table и не добавили в неё маршрут. Пакеты не найдут маршрут и будут отброшены. Обязательно:
/routing/table/add name=ISP2 fibи/ip/route/add ... routing-table=ISP2 -
Порядок правил имеет значение — Mangle обрабатывает правила сверху вниз. Если общее правило стоит выше более специфичного, специфичное никогда не сработает (при passthrough=no). Размещайте более конкретные правила выше общих
-
Двойная маркировка пакетов — если несколько правил mark-packet с passthrough=yes, пакет может получить метку последнего сработавшего правила, а не первого. Используйте passthrough=no для финальных правил маркировки
-
dst-address-type=!local забыли в PBR — без исключения локального трафика DNS-запросы к роутеру, ping роутера и доступ к WebFig будут маршрутизироваться через альтернативный gateway и перестанут работать
-
PCC не балансирует равномерно — PCC работает на основе хеша, и при малом количестве соединений распределение может быть неравномерным. Это нормально — с ростом числа соединений баланс выравнивается. Не пытайтесь "исправить" это добавлением дополнительных правил
-
Mangle без NAT — при PCC и PBR каждый ISP-канал требует собственного правила srcnat. Если трафик, маркированный для ISP2, уходит с source-адресом ISP1, провайдер его отбросит. Добавьте masquerade или src-nat для каждого WAN-интерфейса
# Шаг 1: маркируем соединение (passthrough=yes — идём дальше) /ip/firewall/mangle/add chain=forward \ src-address=192.168.88.0/24 \ connection-state=new \ action=mark-connection new-connection-mark=LAN-traffic \ passthrough=yes comment="Шаг 1: mark connection LAN" # Шаг 2: на основе connection-mark ставим packet-mark /ip/firewall/mangle/add chain=forward \ connection-mark=LAN-traffic \ action=mark-packet new-packet-mark=LAN-packets \ passthrough=no comment="Шаг 2: mark packets LAN" # Маркируем SIP-соединения /ip/firewall/mangle/add chain=forward \ protocol=udp dst-port=5060-5061 \ connection-state=new \ action=mark-connection new-connection-mark=voip-conn \ passthrough=yes comment="VoIP SIP connection" # Маркируем RTP-соединения /ip/firewall/mangle/add chain=forward \ protocol=udp dst-port=10000-20000 \ connection-state=new \ action=mark-connection new-connection-mark=voip-conn \ passthrough=yes comment="VoIP RTP connection" # Маркируем пакеты VoIP для Queue Tree /ip/firewall/mangle/add chain=forward \ connection-mark=voip-conn \ action=mark-packet new-packet-mark=voip-pkt \ passthrough=no comment="VoIP packets for QoS" /queue/tree/add name="VoIP-priority" parent=global \ packet-mark=voip-pkt priority=1 max-limit=2M \ comment="VoIP — максимальный приоритет" # Установить DSCP EF (Expedited Forwarding, 46) для VoIP /ip/firewall/mangle/add chain=postrouting \ connection-mark=voip-conn \ action=change-dscp new-dscp=46 \ passthrough=no comment="DSCP EF для VoIP" # DSCP AF21 (18) для бизнес-трафика /ip/firewall/mangle/add chain=postrouting \ connection-mark=business-conn \ action=change-dscp new-dscp=18 \ passthrough=no comment="DSCP AF21 для бизнес-приложений" # Создаём routing table /routing/table/add name=to-ISP2 fib # Default route для таблицы ISP2 /ip/route/add dst-address=0.0.0.0/0 gateway=198.51.100.1 \ routing-table=to-ISP2 comment="ISP2 gateway" # Маркируем трафик гостевой сети /ip/firewall/mangle/add chain=prerouting \ src-address=192.168.20.0/24 \ dst-address-type=!local \ action=mark-routing new-routing-mark=to-ISP2 \ passthrough=no comment="Гостевая сеть через ISP2" # Routing tables /routing/table/add name=to-ISP1 fib /routing/table/add name=to-ISP2 fib # Маршруты по умолчанию для каждой таблицы /ip/route/add dst-address=0.0.0.0/0 gateway=203.0.113.1 \ routing-table=to-ISP1 /ip/route/add dst-address=0.0.0.0/0 gateway=198.51.100.1 \ routing-table=to-ISP2 # Маркировка соединений для PCC (50/50) /ip/firewall/mangle/add chain=prerouting \ in-interface=bridge-LAN \ connection-state=new \ dst-address-type=!local \ per-connection-classifier=both-addresses:2/0 \ action=mark-connection new-connection-mark=ISP1-conn \ passthrough=yes comment="PCC: 50% через ISP1" /ip/firewall/mangle/add chain=prerouting \ in-interface=bridge-LAN \ connection-state=new \ dst-address-type=!local \ per-connection-classifier=both-addresses:2/1 \ action=mark-connection new-connection-mark=ISP2-conn \ passthrough=yes comment="PCC: 50% через ISP2" # Routing mark на основе connection-mark /ip/firewall/mangle/add chain=prerouting \ connection-mark=ISP1-conn \ in-interface=bridge-LAN \ action=mark-routing new-routing-mark=to-ISP1 \ passthrough=no comment="Route ISP1 connections" /ip/firewall/mangle/add chain=prerouting \ connection-mark=ISP2-conn \ in-interface=bridge-LAN \ action=mark-routing new-routing-mark=to-ISP2 \ passthrough=no comment="Route ISP2 connections" # Address-list с адресами видеоконференций /ip/firewall/address-list/add list=video-services address=meet.google.com /ip/firewall/address-list/add list=video-services address=zoom.us # Маркировка соединений к видеосервисам /ip/firewall/mangle/add chain=forward \ dst-address-list=video-services \ connection-state=new \ action=mark-connection new-connection-mark=video-conn \ passthrough=yes comment="Video conferencing connections" /ip/firewall/mangle/add chain=forward \ connection-mark=video-conn \ action=mark-packet new-packet-mark=video-pkt \ passthrough=no comment="Video conferencing packets" # Upload (из LAN наружу) /ip/firewall/mangle/add chain=prerouting \ in-interface=bridge-LAN \ action=mark-packet new-packet-mark=upload \ passthrough=no comment="Upload traffic" # Download (извне в LAN) /ip/firewall/mangle/add chain=postrouting \ out-interface=bridge-LAN \ action=mark-packet new-packet-mark=download \ passthrough=no comment="Download traffic" # Все правила mangle с счётчиками /ip/firewall/mangle/print stats # Подробная информация /ip/firewall/mangle/print detail # Только правила для конкретной цепочки /ip/firewall/mangle/print where chain=forward # Сбросить счётчики и проверить, растут ли они /ip/firewall/mangle/reset-counters-all # Через несколько секунд проверяем /ip/firewall/mangle/print stats # Посмотреть активные соединения и их метки /ip/firewall/connection/print where connection-mark=voip-conn # Маршруты в конкретной routing table /ip/route/print where routing-table=to-ISP2 # Проверка, что маркированный трафик идёт через правильный gateway /tool/traceroute address=8.8.8.8 routing-table=to-ISP2