FIREWALL / NAT

NAT.

Three NAT scenarios cover almost every small-router setup: masquerade for LAN-to-internet, dst-nat for inbound port forwarding, and hairpin for "let LAN clients reach my public IP." The forward chain still does the filtering — NAT only changes addresses.

1. Masquerade — typical SOHO

One rule. Anything leaving on a WAN-list interface gets the WAN's source address. masquerade is a special form of src-nat that auto-discovers the egress IP, which is what you want behind a dynamic-IP ISP. If you have a static public IP and want it pinned, swap masquerade for src-nat to-addresses=<your-ip>.

masquerade.rsc v6 4 lines · 147 bytes
# typical SOHO masquerade (v6)
/ip firewall nat
add chain=srcnat action=masquerade out-interface-list=WAN \
  comment="mtkf: masquerade WAN egress"
masquerade.rsc v7 4 lines · 147 bytes
# typical SOHO masquerade (v7)
/ip/firewall/nat
add chain=srcnat action=masquerade out-interface-list=WAN \
  comment="mtkf: masquerade WAN egress"

2. dst-nat (port forwarding)

Inbound on the WAN interface, matching a specific port, gets rewritten to an internal IP and (optionally) port. Pair with the forward chain's connection-nat-state=!dstnat drop rule, which the dst-nat flag bypasses cleanly.

dstnat.rsc v6 6 lines · 246 bytes
# port-forward 443 to an internal HTTPS server (v6)
/ip firewall nat
add chain=dstnat action=dst-nat \
  in-interface-list=WAN protocol=tcp dst-port=443 \
  to-addresses=192.168.88.10 to-ports=443 \
  comment="mtkf: dst-nat 443 -> internal https"
dstnat.rsc v7 6 lines · 246 bytes
# port-forward 443 to an internal HTTPS server (v7)
/ip/firewall/nat
add chain=dstnat action=dst-nat \
  in-interface-list=WAN protocol=tcp dst-port=443 \
  to-addresses=192.168.88.10 to-ports=443 \
  comment="mtkf: dst-nat 443 -> internal https"

Order matters. Place this rule above any catch-all src-nat / masquerade in the same table. RouterOS evaluates NAT rules top-to-bottom and stops on the first match.

3. Hairpin NAT

Hairpin NAT solves a specific paper-cut: a LAN client (say, your laptop on 192.168.88.50) tries to reach https://<your-public-ip> — which is your own router. Without hairpin, the dst-nat rewrites the destination to 192.168.88.10 but the reply from .10 goes directly to .50, bypassing the router and breaking the connection (the client expects a reply from the public IP, not from a LAN peer).

Fix: src-nat the LAN-to-LAN-via-public-IP traffic so replies go back through the router and get translated correctly.

hairpin.rsc v6 11 lines · 471 bytes
# hairpin NAT — let LAN clients reach the public IP via the internal address (v6)
# the trick: src-nat the inbound dst-natted connection so the reply goes back through the router

/ip firewall nat
# (1) the existing dst-nat rule from above stays as-is

# (2) src-nat the LAN-to-LAN-via-public-IP traffic
add chain=srcnat action=masquerade \
  src-address=192.168.88.0/24 dst-address=192.168.88.10 \
  protocol=tcp dst-port=443 \
  comment="mtkf: hairpin srcnat for 443"
hairpin.rsc v7 11 lines · 471 bytes
# hairpin NAT — let LAN clients reach the public IP via the internal address (v7)
# the trick: src-nat the inbound dst-natted connection so the reply goes back through the router

/ip/firewall/nat
# (1) the existing dst-nat rule from above stays as-is

# (2) src-nat the LAN-to-LAN-via-public-IP traffic
add chain=srcnat action=masquerade \
  src-address=192.168.88.0/24 dst-address=192.168.88.10 \
  protocol=tcp dst-port=443 \
  comment="mtkf: hairpin srcnat for 443"

Many small-router guides skip hairpin because "use the LAN IP from inside" is a workable workaround. We cover it because the LAN-IP workaround breaks split-DNS setups and any container/VM that shipped with the public hostname baked in.

A note on IPv6

There's no IPv6 NAT in the rules above and there shouldn't be. NAT66 / NPTv6 exist as protocols but the right answer for IPv6 is to route a delegated prefix to LAN clients and let them have routable global addresses. The IPv6 forward chain drops new WAN-ingress traffic — that's the membrane that NAT incidentally provides on IPv4.