So, when you have services available to the world through your external address/hostname, it’s nice to be able to access them via that as well. “Hairpinning” or Hairpin NAT is the term for the NAT redirection required to make this work.
Update 14/3/16: It’s been raised to me that it’s best to use split-DNS for this particular example, but it’s designed to be a simple one for documentation purposes. There’s much better ways of solving the problem, but:
- you don’t always control DNS,
- the service might be entirely IP-based - like IPsec,
- the service might have different internal ports to what’s externally facing (and can’t be reconfigured)
Amongst a whole host of other reasons. Just trust me 😉
Consider the following configuration:
- LAN address space: 10.0.0.0/8
- LAN server IP: 10.0.0.210
- Service is running on: TCP/5222.
- WAN interface: pppoe-out1
- WAN IP: 1.2.3.4
- Router LAN interface: ether2-master-local
The standard source NAT rule to allow masquerade internal clients for accessing the internet is as follows:
/ip firewall nat
; masquerade internal clients
add chain=srcnat action=masquerade out-interface=pppoe-out1
Basically “if it’s going out, NAT it.”
To allow external clients to access an internal service, a destination NAT rule is created. The important part that most documentation doesn’t specify is that you should set the dst-address-type to local, and set the dst-address to the WAN IP instead of just using the WAN interface.
/ip firewall nat
; nat the outside traffic (port forward)
add chain=dstnat action=dst-nat protocol=tcp \
to-addresses=10.0.0.210 to-ports=5222 \
dst-address=1.2.3.4 dst-address-type=local dst-port=5222
To allow internal clients to access the service, a source NAT rule is required.
/ip firewall nat
; nat the inside traffic
add chain=srcnat action=masquerade protocol=tcp src-address=10.0.0.0/8 \
dst-address=10.0.0.210 out-interface=ether2-master-local dst-port=5222
The general idea is that if it’s coming from the local LAN address space, and going to the local LAN address space, masquerade it. You’ll lose the source IP address when doing things like tcpdump etc, but that’s what you get.
References
- Blog post I found on the topic - gave me what I needed to make it work
- It’s discussed further in RFC5128.
- Mikrotik’s TERRIBLY OUTDATED wiki page on Hairpin NAT