Hairpin NAT - but what if there are multiple interfaces!!

According to the experts..
(dynamic WANIP, server is on same subnet as users)
add chain=dstnat action=dst-nat dst-address=!subnetgateway
dst-address-type=local protocol=xxx dst-port=yyyy to-address=serverIP

Since we do not know what the WANIP is, we use the dst-address type-local local.
This tells the router, the packet is going to an interface on the router, could be LAN, could be WAN

But when we define the dst-address we say, destination is anywhere EXCEPT the local LAN.
That leaves only the WAN left…
So the destination is the WAN interface and thus the WANIP.
Or something like that.

(1) Where it falls apart for me, is what happens when there are three LAN subnets 192.168.0.1, 192.168.1.1, and 192.168.2.1 (and the server is 192.168.0.10).
In this case I am lost as the router has two other interfaces to consider.
(2) What If Had the subnet and 5 vlans, what would the router do??
Finally
(3) What if there were two Wans…

Basic dstnat rule is:

/ip firewall nat
add chain=dstnat dst-address=<public address> protocol=<protocol> dst-port=<port> action=dst-nat to-addresses=<internal server>

But there’s a problem with dynamic addresses, you can’t use static dst-address= for them, because it wouldn’t work if address changes. Simple fix is to use dst-address-type=local instead, which matches any address assigned to router. And if your port is something not used by router itself, everything will be fine, you don’t need anything else. It’s not exactly correct, because if you forward e.g. port 23746 to your game server, you want it to work with :23746, but it will also work with 192.168.88.1:23746 (where 192.168.88.1 is router’s LAN address) and all other addresses on router. But who cares, it won’t break anything in 99.99% cases.

Problem is when you try to do the same with port used by router, e.g. port 80 while using WebFig from LAN on 192.168.88.1:80. You won’t be able to connect again, because everything will be forwarded to internal server. And that’s the point of dst-address=!192.168.88.1, it makes the rule apply to any address, except this one. If you need more, you can use address list. Or exclude whole subnet, it it covers all addresses you need, e.g. dst-address=!192.168.0.0/16. But it may not work, because e.g. in case of NAT 1:1, router can have 192.168.x.x also on WAN interface. And you can’t use in-interface=, because that would break hairpin NAT.

Clear?

And for actual hairpin NAT (srcnat rule), as you already know, it’s needed only when client and server are in same subnet. So if you want as little NAT as possible, you’ll need three rules:

/ip firewall nat
add chain=srcnat src-address=192.168.0.0/24 dst-address=192.168.0.0/24 action=masquerade
add chain=srcnat src-address=192.168.1.0/24 dst-address=192.168.1.0/24 action=masquerade
add chain=srcnat src-address=192.168.2.0/24 dst-address=192.168.2.0/24 action=masquerade

That’s if there can be servers with forwarded ports in all three subnets. If you know that there’s some only in one subnet, all you need is one rule for that subnet.

Of course you can be lazy and do e.g.:

/ip firewall nat
add chain=srcnat src-address=192.168.0.0/16 dst-address=192.168.0.0/16 action=masquerade

But it will apply also to connections from e.g. 192.168.2.10 to 192.168.0.10, which is not necessary.

I was thinking more along the lines of… (dynamic wanip scenario)
SubnetA, subnetB, subnetC,
Have a single server, and it its on subnet A.


So why not a dstnat rule (for users on subnet such as):
add chain=dstnat action=src-nat protocol=tcp dst-port=5500
dst-address-list=!LANSUBNETS dst-address-type=local to-address=serverIP

Where firewall address
SubnetA=LANSUNBNETS
SubnetB=LANSUBNETS
SubnetC=LANSUBNETS

Except chain=dstnat and action=src-nat together, you can use address list, I even mentioned that already.

@anav

And that’s the point of dst-address=!192.168.88.1

now this makes sense…
Also @sob, the dst-address-type local would not aplly in cases where the WAN IP is on the ISPs Router which is configured to DMZ to the Mirkotik…
Then the rule on the dst-nat rule should be reversred to invert local since there is no Wan IP on any interface of our Router… just saying…

If you mean dst-address-type=!local, I wouldn’t recommend that. On the upside, if you tried it with ports like 80 or 443, you’d realize your mistake very quickly. :wink:

But you’re right, if the public address is on upstream router and dstnatted to this one (whether it’s called NAT 1:1, DMZ or whatever), then dst-address-type=local alone won’t work (it will for connections from internet, but not for hairpin NAT). In this case you can use dst-address-list= containing public address and private address from WAN interface (to which upstream router forwards everything). Static public address can be entered as such. Dynamic public address requires DDNS hostname. Private address from WAN interface is most likely static, so there’s no problem.

I don’t know if there’s any case when even this address would be dynamic. In theory it’s possible, upstream router could forward everything to first address assigned by its dhcp server. In this case it would require lease script to update address list. Or two rules, one for connections from internet and another for connections from LAN.

@sob whats wrong with !local and ports 80,443 ? I didnt get it…

Just that addresses on your router are local, and all other addresses on whole internet are not local, so dst-address-type=!local will match for all of them.

That is true…