How to Configure NAT on MikroTik (RouterOS 7) – Step by Step

NAT is the first thing every MikroTik router needs to reach the internet, and the first thing every misconfigured router gets wrong. One missing rule, and the whole LAN loses connectivity. One rule in the wrong order, and port forwarding silently fails.

This guide covers NAT on RouterOS 7 from the ground up: masquerade, source NAT, destination NAT, port forwarding, hairpin NAT, static 1:1 mapping with netmap, and the ordering rules that determine whether any of it actually works.

Table of Contents

  1. NAT Fundamentals on RouterOS
  2. srcnat vs. dstnat: What Each Chain Does
  3. Step 1: Basic Masquerade for Internet Access
  4. Masquerade vs. Source NAT: Which to Use
  5. Step 2: Port Forwarding (Destination NAT)
  6. Step 3: Hairpin NAT (NAT Loopback)
  7. Static 1:1 NAT with Netmap
  8. Rule Order: Why It Breaks Silently
  9. NAT and the Firewall Filter Chain
  10. IPv6: Why NAT Usually Does Not Apply
  11. Verify and Test Your NAT Configuration
  12. Common Problems and Fixes
  13. Quick-Reference Configuration Cheat Sheet
  14. Deployment Checklist
  15. Conclusion

NAT Fundamentals on RouterOS

RouterOS manages NAT under /ip firewall nat. A few facts shape every rule you write:

  • Connection tracking is required. NAT depends on connection tracking to remember how each translated session maps back. This is enabled by default on RouterOS 7 and rarely needs manual attention, but it explains why a full connection table can break NAT behavior under heavy load.
  • Two chains exist: srcnat and dstnat. Every NAT rule belongs to one of these two, and each chain processes traffic at a different point in the packet’s path through the router.
  • Rules process top to bottom. The first matching rule in a chain wins, and RouterOS stops evaluating that chain for that packet. Order determines behavior as much as the rules themselves.
  • NAT only applies to new connections. Once a connection is tracked, RouterOS reuses the same translation for the life of that connection without re-evaluating the NAT rules.

srcnat vs. dstnat: What Each Chain Does

  • dstnat — evaluated before routing. Rewrites the destination address of inbound traffic. This is how port forwarding works: a packet destined for your public IP gets its destination rewritten to an internal server before the router decides where to route it.
  • srcnat — evaluated after routing. Rewrites the source address of outbound traffic. This is how your LAN’s private IPs get hidden behind your public WAN IP.

Remembering this order — dstnat first, then routing, then srcnat — explains most of the “why doesn’t my rule work” questions that come up later in this guide.

Step 1: Basic Masquerade for Internet Access

This single rule gives an entire LAN internet access by hiding every internal IP behind the router’s WAN address:

/ip firewall nat add chain=srcnat out-interface=ether1 action=masquerade comment="Masquerade LAN to WAN"
  • Replace ether1 with your actual WAN interface — a PPPoE client, an LTE interface, or a VLAN, depending on your setup.
  • This rule alone is enough for the vast majority of small office and home deployments. Everything else in this guide builds on top of it.

For a more explicit rule scoped to a specific LAN subnet:

/ip firewall nat add chain=srcnat src-address=192.168.88.0/24 out-interface=ether1 action=masquerade comment="LAN subnet to internet"

Masquerade vs. Source NAT: Which to Use

Both actions translate the source address of outgoing traffic, but they behave differently under the hood:

Aspect Masquerade src-nat
Source IP used Automatically picked from the outbound interface Manually specified with to-addresses
Best for Dynamic WAN IPs (DHCP, PPPoE) Static WAN IPs
Behavior on link failure Connection tracking entries are cleared, forcing reconnection Connection tracking entries can persist across a link change
Configuration action=masquerade action=src-nat to-addresses=X.X.X.X

Use masquerade when the WAN interface’s IP address is dynamic, since it always uses whatever address is currently bound. Use explicit src-nat when the WAN IP is static, particularly on multi-WAN setups where connection persistence across a link switch matters.

# Explicit src-nat example, static WAN IP
/ip firewall nat add chain=srcnat src-address=192.168.88.0/24 action=src-nat to-addresses=203.0.113.10 comment="Static WAN source NAT"

Step 2: Port Forwarding (Destination NAT)

Port forwarding exposes an internal service to the public internet by rewriting the destination of inbound traffic:

/ip firewall nat add chain=dstnat in-interface=ether1 protocol=tcp dst-port=80 \
  action=dst-nat to-addresses=192.168.88.10 to-ports=80 comment="Forward HTTP to web server"
  • in-interface=ether1 — restricts the rule to traffic arriving on the WAN interface, preventing LAN-originated traffic from accidentally matching the same rule.
  • protocol=tcp dst-port=80 — matches only HTTP traffic. Add a second rule with dst-port=443 for HTTPS.
  • to-addresses and to-ports — the internal destination the traffic actually gets forwarded to.

Forward a non-standard external port to an internal service’s standard port — common for exposing multiple internal services on the same public IP:

# External port 2222 forwards to internal SSH on port 22
/ip firewall nat add chain=dstnat in-interface=ether1 protocol=tcp dst-port=2222 \
  action=dst-nat to-addresses=192.168.88.20 to-ports=22 comment="SSH via alternate port"

Forward to a specific public IP when the router holds more than one, instead of matching every WAN-bound packet:

/ip firewall nat add chain=dstnat dst-address=203.0.113.10 protocol=tcp dst-port=80 \
  action=dst-nat to-addresses=192.168.88.10 to-ports=80 comment="Forward via specific public IP"

Step 3: Hairpin NAT (NAT Loopback)

Without hairpin NAT, devices on your own LAN cannot reach an internal server using its public IP address — a common surprise after setting up port forwarding, since it works perfectly from outside but fails from inside.

The fix requires a second srcnat rule that masquerades LAN-originated traffic once it has already been redirected internally by the dstnat rule above:

/ip firewall nat add chain=srcnat src-address=192.168.88.0/24 dst-address=192.168.88.10 \
  protocol=tcp dst-port=80 action=masquerade comment="Hairpin NAT for internal web server"
  • Why dst-address is the internal IP, not the public IP: by the time this srcnat rule evaluates the packet, the earlier dstnat rule has already rewritten the destination from the public IP to 192.168.88.10. The hairpin rule must match on that post-translation address.
  • Placement matters. This hairpin rule needs to sit before the general masquerade rule from Step 1, so it matches first for this specific traffic pattern.

Static 1:1 NAT with Netmap

When you have a block of public IPs and want each one mapped permanently to a specific internal host — in both directions — use netmap instead of separate dstnat and srcnat rules:

/ip firewall nat add chain=dstnat dst-address=203.0.113.20 action=netmap to-addresses=192.168.88.30 comment="1:1 NAT inbound"
/ip firewall nat add chain=srcnat src-address=192.168.88.30 action=netmap to-addresses=203.0.113.20 comment="1:1 NAT outbound"

RouterOS has no single bidirectional NAT action — netmap still needs a paired rule in each chain, but each rule provides a full, static 1:1 mapping rather than translating only a single port. This fits scenarios like a public-facing server that needs its own dedicated public IP, distinct from the shared masquerade address used by the rest of the LAN.

Rule Order: Why It Breaks Silently

NAT rules evaluate top to bottom, and the first match wins — RouterOS never checks the rest of the chain once a rule matches. This causes specific, predictable failures:

  • dstnat rules must come before a catch-all srcnat masquerade in terms of overall configuration — though since they live in separate chains evaluated at different points in the packet path, the practical concern is usually within each chain: put specific dstnat rules before broader ones, and specific srcnat rules (like the hairpin rule above) before the general masquerade rule.
  • Order from most specific to least specific within each chain. A broad rule placed early can silently swallow traffic meant for a more specific rule further down.
  • Use /ip firewall nat print to review the actual order — the order rules were created in is not always the order they end up listed in in the GUI.

NAT and the Firewall Filter Chain

NAT rules and firewall filter rules are separate systems that both need to be correct for a service to work end to end:

  • A dstnat rule that forwards a port does not automatically allow that traffic through the firewall filter — /ip firewall filter still needs a rule accepting the forwarded traffic on the forward chain.
  • Add the filter rule matching the same criteria as the NAT rule:
    /ip firewall filter add chain=forward dst-address=192.168.88.10 protocol=tcp dst-port=80 \
      action=accept comment="Allow forwarded HTTP traffic"
  • Place this accept rule before any general drop rule in the forward chain, or the traffic gets dropped after NAT has already rewritten it.

IPv6: Why NAT Usually Does Not Apply

  • IPv6 addressing provides enough address space that hosts get global addresses directly, without the private-address exhaustion problem NAT was built to solve on IPv4.
  • RouterOS supports IPv6 NAT (/ipv6 firewall nat) for edge cases like Carrier-Grade NAT deployments, but standard LAN-to-internet IPv6 connectivity does not need it.
  • Do not carry IPv4 NAT habits into an IPv6 deployment — instead, rely on the IPv6 firewall filter to control access, since there is no address-hiding step doing that job implicitly the way IPv4 masquerade does.

Verify and Test Your NAT Configuration

/ip firewall nat print
/ip firewall nat print stats
/ip firewall connection print
  • /ip firewall nat print stats — shows packet and byte counters per rule. A rule with zero packets after traffic should have matched it points to an ordering or matching problem.
  • /ip firewall connection print — shows active tracked connections, useful for confirming a specific session is being translated as expected.
  • Test from outside the network (a phone on mobile data works well) to confirm port forwarding actually works from the public internet, not just from inside the LAN.

Common Problems and Fixes

LAN has no internet access

  • Cause: No masquerade rule exists, or out-interface does not match the actual WAN interface.
  • Fix: Confirm the WAN interface name with /interface print and match it exactly in the masquerade rule.

Port forward works from outside, fails from inside the LAN

  • Cause: Missing hairpin NAT rule.
  • Fix: Add the hairpin srcnat rule from Step 3, matching on the internal destination IP.

Port forward does not work at all

  • Cause 1: The corresponding firewall filter rule on the forward chain is missing or placed after a drop rule.
  • Cause 2: The dstnat rule’s in-interface does not match the actual WAN interface, so the rule never fires for real inbound traffic.
  • Fix: Check both the NAT rule and the filter rule with print stats to see which one shows zero matched packets.

Some connections randomly drop after a WAN failover

  • Cause: Masquerade clears connection tracking entries on interface changes, forcing every active connection to reconnect.
  • Fix: On multi-WAN setups with a static IP, use explicit src-nat instead of masquerade to allow tracked connections to persist across a link switch.

NAT rule shows zero matched packets in stats

  • Cause: A rule earlier in the same chain is matching the traffic first.
  • Fix: Review rule order with /ip firewall nat print and move more specific rules above broader ones.

Quick-Reference Configuration Cheat Sheet

# Basic masquerade — LAN to internet
/ip firewall nat add chain=srcnat out-interface=ether1 action=masquerade

# Static WAN — explicit source NAT
/ip firewall nat add chain=srcnat src-address=192.168.88.0/24 action=src-nat to-addresses=203.0.113.10

# Port forward (destination NAT)
/ip firewall nat add chain=dstnat in-interface=ether1 protocol=tcp dst-port=80 \
  action=dst-nat to-addresses=192.168.88.10 to-ports=80

# Hairpin NAT
/ip firewall nat add chain=srcnat src-address=192.168.88.0/24 dst-address=192.168.88.10 \
  protocol=tcp dst-port=80 action=masquerade

# Static 1:1 NAT (netmap)
/ip firewall nat add chain=dstnat dst-address=203.0.113.20 action=netmap to-addresses=192.168.88.30
/ip firewall nat add chain=srcnat src-address=192.168.88.30 action=netmap to-addresses=203.0.113.20

# Required firewall filter rule for forwarded traffic
/ip firewall filter add chain=forward dst-address=192.168.88.10 protocol=tcp dst-port=80 action=accept

# Verify
/ip firewall nat print stats
/ip firewall connection print

Deployment Checklist

  • Confirm the correct WAN interface name before writing any rule
  • Add one masquerade or src-nat rule for general LAN internet access
  • Use masquerade for dynamic WAN IPs, explicit src-nat for static ones
  • Add a dstnat rule per forwarded service, scoped with in-interface where possible
  • Add the matching firewall filter accept rule for every forwarded port
  • Add hairpin NAT for any internal server that LAN clients also need to reach by public IP
  • Use netmap for full 1:1 static mappings, not repeated single-port dstnat rules
  • Order rules from most specific to least specific within each chain
  • Verify with /ip firewall nat print stats, not just visual inspection
  • Test port forwards from an actual external network, not just from inside the LAN

Conclusion

NAT on RouterOS 7 comes down to two chains and a handful of patterns: masquerade for outbound LAN traffic, dstnat for port forwarding, hairpin NAT for internal access to forwarded services, and netmap for full static mappings. Nearly every “NAT doesn’t work” ticket traces back to rule order or a missing firewall filter rule, not the NAT configuration itself. Check both, in that order, before assuming the NAT rule is wrong.


Check our list of MikroTik guides

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *