Victor is a full stack software engineer who loves travelling and building things. Most recently created Ewolo, a cross-platform workout logger.
Setup port forwarding with hairpin NAT on Mikrotik CCR2004-1G-12S+2XS with dual networks

We recently got a fiber internet connection and with it came a fancy Mikrotik CCR2004-1G-12S+2XS router. As it turns out this router does not have Wireless capability so I still needed to keep my ASUS for a wifi connection. The cool part though is that the PC in the home office could now avail of a LAN connection directly from the Mikrotik router. I did run into a few hiccups trying to get port forwarding working properly between the Mikrotik and the ASUS routers. This article documents how I managed to set it up including letting the PC from the home office access machines behind the ASUS router.

Home network setup

This guide assumes that the mikrotik router is setup and that you have administrative access to RouterOS (I've only used the webfig on http://192.168.88.1). Here's a quick diagram of my home network setup.

I'm no networking guru.
References

https://help.mikrotik.com/docs/display/ROS/NAT#NAT-HairpinNAT explains the issue of Hairpin NAT and why it is required.

https://www.youtube.com/watch?v=_kw_bQyX-3U is an excellent video tutorial showing how to setup port forwarding with Hairpin NAT for dynamic IPs. If you do not have a dual network setup then this video tutorial should be enough to get going.

Mikrotik forum including some very detailed posts from real networking gurus, in particular https://forum.mikrotik.com/viewtopic.php?f=13&t=175064&p=856786&hilit=hairpin+nat#p856786 and https://forum.mikrotik.com/viewtopic.php?f=2&t=162321.

The basics

This guide assumes that the internet bridge/interface on the Mikrtotik router is named wan and the local ethernet ports are bridged on lan. We also assume that the ASUS router and the PC has a static IP address lease (via DHCP). Setting up port forwarding on the Mikrotik router is pretty straightforward. In the example below we forward requests coming from the outside (interface wan) to the ASUS router. The ASUS router is responsible for forwarding the packets on to the correct machine.


/ip firewall nat
add action=dst-nat chain=dstnat dst-port=80 in-interface=wan protocol=tcp to-addresses=192.168.100.101 to-ports=80

In some situtations it might be required to explicitly allow the firewall to let port forwarded packets through.


/ip firewall filter
add action=accept chain=foward comment="Allow port forwarding" connection-nat-state=dstnat connection-state=new disabled=no in-interface=wan

The above should be enough to be able to access the webserver from outside of the home network, e.g. curl http://your.public.ip However, when trying to connect to the webserver from inside the network, we run into the issue that the packets which are received back from the webserver are expected to be from the external ip and not from an internal one.

This is solved by setting up what is known as a hairpin NAT which tells the router to route packets destined for the public ip locally but pretend that the packets came from the outside.

Hairpin NAT

We enable hairpin NAT by first setting up a masquerade for the internal network. Note that this rule needs to be the first one in the list of rules (drag and drop to the top in webfig).

  
/ip firewall nat
add action=masquerade chain=srcnat comment="HAIRPIN NAT" dst-address=192.168.100.0/24 src-address=192.168.100.0/24

We now need to setup a destination address to the port forwarding rule. In the situation that we have a static IP address from the ISP then we can simply put that in and we are done. In most cases however, we have a dynamic IP address. To work around this issue, we will use Mikrotik's dynamic DNS update feature and create an address list which we will then use for our port forwarding rule.

  
/ip cloud
set ddns-enabled=yes
/ip firewall address-list
add address=d4f00e6306da.sn.mynetname.net list=WAN-IP

# modify the above rule setup to add the destination address list
/ip firewall nat
add action=dst-nat chain=dstnat dst-address-list=WAN-IP dst-port=80 in-interface=wan protocol=tcp to-addresses=192.168.100.101 to-ports=80

This far, we have pretty much followed the instructions in the video tutorial. This is enough if your webserver is sitting directly behind the Mikrotik router. In my case, I needed an extra rule that actually forwarded packets coming from the local network to the external IP straight to the ASUS router:

  
/ip firewall nat
add action=dst-nat chain=dstnat dst-address-list=WAN-IP dst-port=80 in-interface=lan protocol=tcp src-address=192.168.100.0/24 to-addresses=192.168.100.101 to-ports=80

With this I was now able to access the webserver directly from the PC on the Mikrotik network as well as have it available from the outside :). Please note that all addresses and examples provided are for illustrative purposes only, I do have a Pi but it is not running a webserver 24/7.

Backup configuration

As always, before fiddling with any settings be sure to backup your configuration:

  
ssh admin@192.168.100.1 '/export' \
  | tr -d '\r' \
  | awk '{sub(/^ +/, "", $0); if (sub(/\\$/,"")) printf "%s", $0; else print $0}' \
  | sed "s/^# .* by RouterOS/# RouterOS/" \
  | sed "/^# managed by CAPsMAN$/d" \
  | sed "/^# channel: .*, CAPsMAN forwarding$/d" \
  | sed "/^# $/d" \
  > mikrotik-backup.rsc