info_i_25x25.png See important information about Ubiquiti Devices and KRACK Vulnerability in this article. We will update this document as more information becomes available.

EdgeRouter - NAT Hairpin (Nat Inside-to-Inside / Loopback / Reflection)


Readers will learn about the NAT Hairpin for EdgeRouter.

Typically, a NAT Port Forwarding rule is used from the outside network to get to a server on the inside network by using the public address of the router (or hostname). But in cases where the same local server address must be accessed from inside the local network, NAT Hairpin applies. A user might prefer doing this for ease of use. For example, if a user has a laptop and a mailserver on a network locally, he will prefer to use the same server name when local and when away to avoid having to change settings every time. 

NAT Hairpin is also know as "NAT inside-to-inside," or, "NAT Loopback," or, "NAT Reflection," and probably some others.

Note: As of version v1.4.0 there is now a port forward wizard in the GUI that makes NAT hairpin much easier (hairpin is a check box).


For this example we'll start with the example SOHO configuration, as seen in the the diagram below.

Example SOHO diagram to be used in NAT hairpin configuration.

First we'll add a Destination NAT (i.e. port forward) rule so that port 2222 gets forwarded to on TCP port 22. This is the outside-to-inside NAT request for WAN packets arriving on the public-facing interface, eth2 (NAT Hairpin is later).

Note: The Destination Address (bottom) isn't required if the translated address is the same prior to and after NAT.

Next, we need to add a firewall rule to WAN_IN to allow this flow. One of the most confusing things with adding a firewall rule for destination NAT is that DNAT happens before the firewall, so the firewall rule must match the translated address (and port). For example:

Now when we test our port forward from the outside network, we can see both the firewall packet stats increase as well as the NAT count.

Note: Firewall stats are packet/byte counters while NAT count is according to session.

From the CLI we can also see the active translation:

ubnt@ubnt:~$ show nat translations
Pre-NAT Post-NAT Type Prot Timeout dnat tcp 3321 

Now we want to add NAT Hairpin rules. We basically need:

  1. A copy of the initial DNAT rule modified for the LAN interface. This is the inside-to-inside NAT request for LAN packets arriving on the local interface, eth0.
  2. A new NAT Masquerade rule for the LAN interface.

With these 2 new NAT rules, we should be able to use the same public address to get back to the internal server. In my example, my public address is, so the original flow looks like --> TCP 2222

Then the DNAT rule translates it to: --> TCP 22

Then the SNAT rule translates it to: --> TCP 22

Since the 2 DNAT rules are identical except for the interface, we could delete the 2nd DNAT rule and modify the first from "eth2" to the ethernet wildcard of "eth+" (when other Inbound Interface is selected) as seen below:

 The final config for this example can be downloaded from: NAT Hairpin Config