Back to blog

MikroTik / RouterOS  ·  Routing  ·  July 2026

MikroTik
Policy Routing with Rules & Mangle

Same goal as Cisco PBR — route by who sent the packet, not just where it's going — but RouterOS gets there two different ways, and knowing which to reach for is half the battle. Routing rules for the simple src/dst cases; mangle routing-marks for anything that needs connection awareness. The twin of the Cisco Policy-Based Routing post.

MikroTik RouterOS Policy Routing Mangle Routing Marks Dual-WAN

RouterOS gives you two policy-routing tools, and picking the right one avoids a lot of pain. Routing rules (/routing rule) are the lightweight option: match on source/destination/interface and send the lookup to a different routing table — fast, stateless, perfect for "this subnet uses that table." Mangle routing-marks are the powerful option: mark a packet (or a whole connection) in the firewall, then route by that mark — which lets you decide on anything the firewall can match (port, protocol, connection state) and, crucially, keep a flow pinned to one WAN for its whole life.

The distinction that matters: routing rules can't see connections, so for dual-WAN you almost always want the mangle + connection-mark + routing-mark pattern, so a reply comes back the same way the request left. This is the RouterOS counterpart to Cisco PBR — one set ip next-hop route-map there, two distinct mechanisms here.

Prerequisites

01

The Simple Case — Routing Rules

When the decision is purely "this source uses that path," routing rules are the cleanest tool: a route in a named table, and a rule that points matching traffic at it.

RouterOS 7 — guest subnet uses ISP-B's table
# A default route living in its own routing table (v7 uses routing-table=).
/routing table add name=via-ISP-B fib
/ip route add dst-address=0.0.0.0/0 gateway=203.0.113.9 routing-table=via-ISP-B

# Rule: guest source -> look up in via-ISP-B instead of main.
/routing rule
add src-address=10.10.20.0/24 action=lookup-only-in-table table=via-ISP-B
# Everything else falls through to the main table normally.
⚠ Gotcha — lookup vs lookup-only-in-table

action=lookup tries your table and then falls back to main if there's no match — handy, but it means a dead gateway in your table silently reverts to the default path (sometimes good, sometimes a surprise). action=lookup-only-in-table is strict: match this table or drop, no fallback. For dual-WAN failover you usually want lookup so a dead ISP-B falls back to ISP-A; for hard isolation (guest must never use ISP-A) you want lookup-only-in-table. Choose deliberately.

02

The Powerful Case — Mangle Marks

When the decision depends on ports, protocols, or must survive as a connection, mark the connection once and the packets thereafter, then route by the mark. This is the workhorse pattern for real dual-WAN.

RouterOS 7 — mark VoIP onto ISP-A, pin the whole connection
/ip firewall mangle
# 1. Mark the CONNECTION on the first packet (here: SIP/RTP).
add chain=prerouting protocol=udp port=5060,10000-20000 \
    connection-state=new action=mark-connection new-connection-mark=voip-conn passthrough=yes
# 2. Turn the connection-mark into a ROUTING-mark on every packet of it.
add chain=prerouting connection-mark=voip-conn \
    action=mark-routing new-routing-mark=via-ISP-A passthrough=no

# 3. A default route in that routing table.
/ip route add dst-address=0.0.0.0/0 gateway=198.51.100.1 routing-table=via-ISP-A
💡 Why Connection-Mark First, Then Routing-Mark

The two-step — mark-connection on the new packet, then mark-routing from that connection-mark — is the pattern that keeps a flow on one WAN for its entire life. Match only per-packet and a mid-connection classification change (or an unmarked return packet) can split a flow across both links, breaking stateful NAT and anything the far end tracks. Marking the connection once and deriving the routing-mark from it guarantees symmetry. It's the single most important habit in RouterOS policy routing, and the reason mangle beats bare routing rules for dual-WAN.

03

Don't Forget NAT and Return Traffic

Policy-routed traffic still has to be NATed out the interface it's actually leaving by, and replies must find their way back. Two rules people forget, and the symptoms are baffling.

RouterOS 7 — a masquerade per WAN, keyed on out-interface
/ip firewall nat
add chain=srcnat out-interface=ISP-A-link action=masquerade
add chain=srcnat out-interface=ISP-B-link action=masquerade
# Each WAN NATs what leaves it. Without the matching masquerade, traffic
# policy-routed out ISP-B leaves with an ISP-A-shaped source and is dropped.
# For inbound-initiated flows on the secondary WAN, also mark connections
# arriving on ISP-B so their replies route back out ISP-B (same 2-step).

04

Verify the Marks Land Safe to Run

Every stage has a counter. Walk them in order — mangle hits, the mark on the connection, the route chosen — and the break is always at one identifiable step.

RouterOS 7 — the mark-tracing walk
/ip firewall mangle print stats      # do the mark rules have packet counts?
/ip firewall connection print where connection-mark=voip-conn
/routing rule print                    # rules present and ordered
/ip route print where routing-table=via-ISP-A
# From a marked host, a traceroute should exit the intended WAN gateway.
SymptomWhere to look
Traffic ignores the policyMangle rule not matching (wrong chain/port), or route in wrong table.
Flow splits across both WANsMarked per-packet, not per-connection — use the 2-step connection→routing mark.
Leaves right WAN, no repliesMissing per-WAN masquerade, or return path not marked.
Dead ISP-B kills guest internetlookup-only-in-table with no fallback — switch to lookup.

Takeaways

  1. RouterOS has two policy-routing tools: routing rules (simple, stateless, src/dst) and mangle routing-marks (powerful, connection-aware). Pick per job.
  2. For real dual-WAN, use mangle — routing rules can't keep a flow pinned to one WAN.
  3. Mark the connection first, then derive the routing-mark — this guarantees a flow stays on one link and its replies return symmetrically.
  4. lookup falls back to main; lookup-only-in-table doesn't. Choose based on whether a dead path should fail over or stay isolated.
  5. Add a masquerade per WAN keyed on out-interface, or policy-routed traffic leaves with the wrong source and dies.
  6. Every stage has a counter — trace mangle hits → connection mark → chosen route to find the break.

Dual-WAN that sends the wrong traffic down the wrong link?

NOCTIS builds connection-aware policy routing on MikroTik and Cisco across Crete — guest, VoIP, and backups each on the right path, pinned per-connection, with clean NAT and failover.

Book a Discovery Call →