// DevOps

MikroTik: return traffic via the same gateway it came in on

Published on 2026-06-24

There is a MikroTik router that goes to the Internet via WAN1. While there is only one gateway — everything works. As soon as a second WAN, a VPN tunnel with BGP routes, or just specific /32 prefixes appear in the main routing table — the classic problem begins: the request arrives via WAN1, but the reply goes out via WAN2 or the VPN. The client sees RST or waits for a timeout.

Client → [WAN1] → MikroTik --dstnat--> 192.168.1.10
Client ← [WAN2] ← MikroTik <-----------  reply

This is asymmetric routing. It manifests in two different scenarios, and each requires its own approach.


Why RouterOS does this

When it needs to send a packet, RouterOS looks into the main routing table and picks the best route to the destination address. If there are multiple default routes in main or BGP has injected its prefixes there — the router can legitimately choose a different interface. It is not obliged to “remember” where the original request came from. This is normal L3 router behavior, which in this case gets in the way.


Two scenarios

Scenario 1 — port forwarding (dstnat). A request arriving on WAN1 is forwarded to an internal server via dstnat. The server’s reply goes back through the router, and the router chooses the interface based on the main table. If there is a specific route to the source address there — the reply will go elsewhere.

Scenario 2 — direct connections to the router. SSH, ICMP, API, Winbox — anything addressed to the router itself. The request came in via WAN1, the router generates a reply and again looks in main. If BGP has a route for the source address — the reply goes via VPN or WAN2.

Both scenarios are solved using a single isolated routing table, but the mangle rules for them are different.


Preparation: separate routing table

Create an isolated routing table with a single route — the default via 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

That’s it. Nothing else should be added to this table.


Mangle rules

You need four rules. Order matters — they must appear in this exact sequence.

Rule 1 — mark dstnat connections

Triggers on ingress via WAN1 only for packets that have gone through dstnat. Marks the whole connection:

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"

Rule 2 — routing-mark for dstnat connections

Catches all packets of the marked dstnat connection, including replies from LAN, and sets their 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"

Rule 3 — mark direct connections to the router

Same conditions as in rule 1, but for non-dstnat traffic — SSH, ICMP and everything else addressed directly to the router:

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"

Rule 4 — routing-mark for router replies

And here is the critically important detail: the output chain, not 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"

Why rule 4 is in output, not prerouting

This is the main trap. The first instinct is to put mark-routing in prerouting by analogy with rule 2. It looks logical, but it breaks the router.

mark-routing in prerouting affects the routing decision for the current packet. For forwarded packets (those passing through the router) this works correctly. But for packets addressed to the router itself, RouterOS also applies that routing-mark. The router looks for its own address (94.102.124.79) in the via-wan1 table, finds only the default 0.0.0.0/0 → <WAN1_GATEWAY> and tries to forward the packet to the upstream gateway instead of accepting it locally. SSH drops immediately, the router becomes unavailable.

# What the error looks like:
# Incoming SSH packet → mark-connection from-wan1 → mark-routing via-wan1 →
# RouterOS looks for 94.102.124.79 in via-wan1 →
# finds only 0.0.0.0/0 → gateway →
# forwards to the provider instead of processing locally →
# connection fails

The output chain only processes packets that the router itself generates in reply. This is exactly where the routing-mark must be set — after the router has accepted the packet and is forming the response.


How it works internally

dstnat connection (port forwarding):

  1. Packet enters via WAN1
  2. Connection tracking sees that the connection will go through dstnat
  3. Rule 1: connection-mark=from-wan1-dstnat
  4. Rule 2: routing-mark=via-wan1
  5. dstnat changes the dst address to 192.168.1.10
  6. The server receives the request and generates a reply
  7. The reply enters via the LAN interface → prerouting
  8. Rule 2 triggers again by the connection mark → routing-mark=via-wan1
  9. The reply goes out via WAN1

Direct connection to the router (SSH, ping):

  1. Packet enters via WAN1
  2. Rule 3: connection-mark=from-wan1
  3. The router accepts the packet (input chain)
  4. The router generates a reply (output chain)
  5. Rule 4: routing-mark=via-wan1
  6. The reply goes out via WAN1, bypassing any specific routes in main

Things to note

Fasttrack. If fasttrack is enabled (connection-state=established,related), it bypasses mangle for established connections. In typical configurations fasttrack is enabled by default. The rule with passthrough=no must be placed before fasttrack, otherwise post-handshake connections will skip past the mangle rules.

BGP. In BGP environments the problem is more pronounced — BGP can inject thousands of specific prefixes, and for any of them the main table may choose the wrong interface. The isolated via-wan1 table does not react to that — it contains only the default.

Multiple WANs. The scheme scales: for WAN2 create a via-wan2 table, a default via the second gateway, and four analogous rules. The tables do not interfere with each other.


Verification

Check that the mangle rule counters show the rules are actually firing:

routeros
/ip firewall mangle print stats

Active connections with the desired marks:

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

Route in the isolated table:

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

Summary

RuleChainWhat it does
mark-connection (dstnat)preroutingMarks port-forwarded connections from WAN1
mark-routing (dstnat)preroutingRoutes dstnat replies via via-wan1
mark-connection (!dstnat)preroutingMarks direct connections to the router from WAN1
mark-routing (!dstnat)outputRoutes router replies to WAN1 connections via via-wan1

The routing table is the same for both scenarios. The rules for dstnat and direct connections work independently, do not interfere with each other, and do not affect other traffic.

// Reviews

Related reviews

ladohinpy

MikroTik hAP router setup. I'll set up a MikroTik Wi‑Fi router for you.

2025-07-21 · ★ 5/5

An excellent specialist, a savvy expert, and a wonderful person. In an hour he fixed what we'd been racking our brains over for days! I'm sure this won't be the last time we rely on his boundless professionalism.

An excellent specialist, a savvy expert, and a wonderful person. In an hour he fixed for us what we had been scratching our heads over for days! I'm sure this won't be the first time we make use of his boundless …

Ravenor

MikroTik hAP router setup. I'll configure a MikroTik Wi-Fi router for you.

2025-05-28 · ★ 5/5

// Contact

Need help?

Get in touch with me and I'll help solve the problem

Message on Telegram

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

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

Write and get a quick reply