Community discussions

MikroTik App
 
doctorpangloss
just joined
Topic Author
Posts: 5
Joined: Thu Jun 11, 2020 1:07 am

Hairpin NAT: Is there a simple solution?

Thu Jun 11, 2020 1:14 am

What command do I issue to enable hairpin NAT?

It was a challenge just to discover that the name for this behaviour is called hairpin NAT. For future Googlers, hairpin NAT describes the super conventional behavior that when you access your WAN IP address from your LAN, traffic that would get forwarded to another computer on your network (e.g. port forwarding) is modified to appear to come from your router instead, in order to make such traffic work correctly inside your LAN. This is the default behavior for pretty much everything but Microtik.

I use the Microtik extremely conventionally. I use UPnP to configure inbound ports, my WAN IP is dynamic - this is representative of the average US Internet user.

When I visit https://wiki.mikrotik.com/wiki/Hairpin_NAT I see configurations commands that correspond to a very specific kind of configuration.

I would like a general, one time, end-all-be-all way to enable hairpin NAT. No knowledge of my specific internal or external networking required. I am using as close to stock MicroTik configuration as possible.

By comparison, enabling internal DNS names from the hostnames DHCP clients advertise was... not that challenging. I copied and pasted a script that runs every 5 seconds or whatever. This is acceptable! I would prefer a correct and never-needs-to-be-touched-again solution to one that requires me to know which ports I have forwarded where or what my external IP address is.

dd-wrt uses iptables and must have rules that implement this. So what are the rules?

Once it is authored here, I will happily edit the MicroTik Wiki to contain the commands! Personally, if I was a developer, Hairpin NAT is such a fundamental and basic feature / expectation of router behavior that I would add it to Quick Set.
 
anav
Forum Guru
Forum Guru
Posts: 4606
Joined: Sun Feb 18, 2018 11:28 pm
Location: Nova Scotia, Canada

Re: Hairpin NAT: Is there a simple solution?

Thu Jun 11, 2020 6:18 pm

To funny, and by the way, its not a limitation on the MT, its up to the user as per many other functions to program that into the router.
If you want a consumer router..........................

As for hairpin NAT, it is only required when the user is on the same subnet of the Server that one is trying to reach via WANIP.
Being a simple homeowner I have never understood this approach as I always have used the lanip directly.

In any case, its quite simple one adds another source nat rule as a top srcnat rule in the following format
add chain=src-nat action=masquerade src-address={subnet of server} dst-address={subnet of server}

If you have a static/fixed WANIP, then no change is required to the dst nat rule which will have in it (dst-address=WANIP)
For dynamic WANIPs the dst nat rule usually has something like in-interface-list=WAN, which we replace with dst-address-list=external_wan
where externel_wan is a firewall address list entry with an address=DDNSname ***

*** Enable IP Cloud DDNS, copy DDNS name into the address above, done!
I'd rather manage rats than software. Follow my advice at your own risk! (Sob & mkx forced me to write that!)
 
User avatar
Jotne
Forum Guru
Forum Guru
Posts: 1743
Joined: Sat Dec 24, 2016 11:17 am
Location: jo.overland at gmail.com

Re: Hairpin NAT: Is there a simple solution?

Thu Jun 11, 2020 10:59 pm

If you just have one web server and you have a DNS server on your router, you can add a static DNS entry to it.
Example you server is www.cnn.com and internal IP is 192.168.88.10, then just add a DNS with that informatin.
User on outside will use the public IP and user on inside will use the inside IP.

DNS have som + and -, same as Hairpin NAT has.
 
How to use Splunk to monitor your MikroTik Router(s)

MikroTik->Splunk
 
 
Sob
Forum Guru
Forum Guru
Posts: 5590
Joined: Mon Apr 20, 2009 9:11 pm

Re: Hairpin NAT: Is there a simple solution?

Fri Jun 12, 2020 12:08 am

For dynamic WANIPs the dst nat rule usually has something like in-interface-list=WAN, which we replace with dst-address-list=external_wan
where externel_wan is a firewall address list entry with an address=DDNSname
If you have public address directly on router, you can skip DDNS and use this as DHCP lease script:
:if ($bound=1) do={
  /ip firewall address-list set [/ip firewall address-list find where comment="wan1ip"] address=$"lease-address" disabled=no
} else={
  /ip firewall address-list set [/ip firewall address-list find where comment="wan1ip"] disabled=yes
}
It assumes that you have address list item like this:
/ip firewall address-list
add comment=wan1ip disabled=yes list=external_wan
The advantage over relying on DDNS is that updates are instant. DDNS method is useful when there's NAT 1:1 and router itself doesn't have public address.
People who quote full posts should be spanked with ethernet cable. Some exceptions for multi-topic threads may apply. Not intended as incentive for masochists.
 
anav
Forum Guru
Forum Guru
Posts: 4606
Joined: Sun Feb 18, 2018 11:28 pm
Location: Nova Scotia, Canada

Re: Hairpin NAT: Is there a simple solution?

Fri Jun 12, 2020 1:38 am

I don't understand what you did at all. Surprise LOL.

What in plain words does the script do, and the firewall address list item disabled is also confusing.

(I swear you spend all your free time coming up with ways to give me a brain bleed)
I'd rather manage rats than software. Follow my advice at your own risk! (Sob & mkx forced me to write that!)
 
Sob
Forum Guru
Forum Guru
Posts: 5590
Joined: Mon Apr 20, 2009 9:11 pm

Re: Hairpin NAT: Is there a simple solution?

Fri Jun 12, 2020 2:01 am

It's an alternative to your:
/ip firewall address-list
add list=external_wan address=<DDNS hostname>
Script goes to:
/ip dhcp-client
add interface=<WAN> <other options> script="<the script I posted>"
You can skip the else branch if you want, it happens when the lease is lost and in that case you don't have internet access anyway (unless you have another WAN). And when it comes back, the address in list will be updated immediatelly.

(And no, I don't :D)
People who quote full posts should be spanked with ethernet cable. Some exceptions for multi-topic threads may apply. Not intended as incentive for masochists.
 
anav
Forum Guru
Forum Guru
Posts: 4606
Joined: Sun Feb 18, 2018 11:28 pm
Location: Nova Scotia, Canada

Re: Hairpin NAT: Is there a simple solution?

Fri Jun 12, 2020 3:34 am

I understand my config line, I dont understand what the script is doing.
In plain words...... each line.
I'd rather manage rats than software. Follow my advice at your own risk! (Sob & mkx forced me to write that!)
 
mkx
Forum Guru
Forum Guru
Posts: 4317
Joined: Thu Mar 03, 2016 10:23 pm

Re: Hairpin NAT: Is there a simple solution?

Fri Jun 12, 2020 8:28 pm

In plain words...... each line.

I'll try to translate it to NovaScotiaish for you:
1|
2| :if ($bound=1) do={
3|   /ip firewall address-list set [/ip firewall address-list find where comment="wan1ip"] address=$"lease-address" disabled=no
4|  } else={
5|   /ip firewall address-list set [/ip firewall address-list find where comment="wan1ip"] disabled=yes
6| }
  1. brewery's cart enters the yard
  2. did it bring a full cask?
  3. it did actually ... so find that cask in the cellar tagged with "local ale" and pump contents of the new one into the existing. And open the valve (doesn't matter if it was open already) on the pipe towards bar
  4. hummm, what to do if there's no full cask on the cart?
  5. drats, close the valve on the old cask in the cellar (the one tagged with "local ale").
  6. go back behind the bar, observe cart leaving the yard
BR,
Metod
 
Sob
Forum Guru
Forum Guru
Posts: 5590
Joined: Mon Apr 20, 2009 9:11 pm

Re: Hairpin NAT: Is there a simple solution?

Fri Jun 12, 2020 11:11 pm

Wow, what an explanation! I couldn't write better myself. :D
People who quote full posts should be spanked with ethernet cable. Some exceptions for multi-topic threads may apply. Not intended as incentive for masochists.
 
anav
Forum Guru
Forum Guru
Posts: 4606
Joined: Sun Feb 18, 2018 11:28 pm
Location: Nova Scotia, Canada

Re: Hairpin NAT: Is there a simple solution?

Sat Jun 13, 2020 6:45 pm

Now we are getting somewhere, student MKX.
We have tapped into your creative side of the force!!
(and such modesty sob!! truly touching)

anav (yoda) MTUNA.
I'd rather manage rats than software. Follow my advice at your own risk! (Sob & mkx forced me to write that!)
 
anav
Forum Guru
Forum Guru
Posts: 4606
Joined: Sun Feb 18, 2018 11:28 pm
Location: Nova Scotia, Canada

Re: Hairpin NAT: Is there a simple solution?

Sat Jun 13, 2020 7:05 pm

Well every router I have used has a public IP address so it is not clear to me if you mean static or dynamic (okay I will assume dynamic).
What do leases have to do with dstnat rules and more specifically the replacement of dst-address=, dst-address-list=, OR in-interface-list=WAN.

Furthermore if it directly replaces DDNS then the script seems to SAY okay the router is bound (assuming by ISP wanip connection) check for an address list entry with specific text and it finds it, then stick a value of leased address (that is bounded) there (okay I will buy the lease given by the IP to the router). So that may work. What I dont understand, is the second case, are you saying if I cannot find
a. the address list entry OR
b. cannot find a lease by the ISP (there is no connection to the ISP)

then dont stick the non-existing lease address/IP in the firewall address list?????

If so what is the use of that, why wouldnt there be a lease? So you disable the script but left the op without an ISP connection.
How thoughtful.
The script should say
if not bound SEND EMAIL as a minimum to warn the OP that his.her internet is down ;-P

PS where do you stick this script under system scripts??
I'd rather manage rats than software. Follow my advice at your own risk! (Sob & mkx forced me to write that!)
 
Sob
Forum Guru
Forum Guru
Posts: 5590
Joined: Mon Apr 20, 2009 9:11 pm

Re: Hairpin NAT: Is there a simple solution?

Sun Jun 14, 2020 1:23 am

If you have static public address, you can simply use dst-addres=<your public address> and not worry about anything. Lease script is for dynamic public address, but it must be on router (no NAT 1:1). And since it's DHCP lease script, guess where it goes (you can scroll a little back, I did write it; same for 'else' branch).

And sending mail... I don't know how often your internet goes down, mine maybe once or twice a year. Every single time I think "ok, so I can't do the thing I wanted to do, no problem, I'll just check mail or something instead". And next thought is "damn it!", every single time too, guess why.
People who quote full posts should be spanked with ethernet cable. Some exceptions for multi-topic threads may apply. Not intended as incentive for masochists.
 
anav
Forum Guru
Forum Guru
Posts: 4606
Joined: Sun Feb 18, 2018 11:28 pm
Location: Nova Scotia, Canada

Re: Hairpin NAT: Is there a simple solution?

Sun Jun 14, 2020 3:33 am

Sob, on the grounds that I might incriminate my own failings, I refuse to state why an email from the router would not work if there was not DHCP client lease LOL.
Also Yes, I see now you have already answered the questions. Unfortunately I already have a script in my dhcp client to take the gateway that is bound and stick in my route rule.

add default-route-distance=255 disabled=no interface=vlanbell
script="\":if (\
\\\$bound=1) do={ /ip route set [find commen\\\r\
\nt=\\\"BellFibre\\\"] gateway=(\\\$\\\"gateway-address\\\") disabled=no; \
:log warning\\\r\
\n\\_(\\\"New ISP1 gateway: \\\".(\\\$\\\"gateway-address\\\")) }\"" \
use-peer-dns=no use-peer-ntp=no


Would it be possible to add another script without interference either way. The one you suggested does not seem to conflict?
Just for arguments sake as I am sane and rational and only use lanip to access a server when behind the router ;-PPPP
I'd rather manage rats than software. Follow my advice at your own risk! (Sob & mkx forced me to write that!)
 
sindy
Forum Guru
Forum Guru
Posts: 5343
Joined: Mon Dec 04, 2017 9:19 pm

Re: Hairpin NAT: Is there a simple solution?

Sun Jun 14, 2020 10:05 am

Would it be possible to add another script
yes
without interference either way
no.

To clarify: the script associated to the dhcp client is run every time the lease status and/or contents changes, no matter how (address acquired, address not renewed, address changed, probably also e.g. address the same like last time but gateway/route list changed). To determine the type of change and possibly take an appropriate action, the script has to check the values in available variables.

So you have to augment your existing dhcp script with additional actions, or you may create several pinpointed scripts under /system script and let the dhcp script just invoke them. Rule of thumb - what fits to a single screen may stay like that, what doesn't cannot be seen without scrolling anyway so better to split it into blocks fitting to a single screen each. Specially for Mikrotik and command line, editing of a dhcp script lacks the colored syntax check available when editing scripts at other places, so it is a bit painful to debug, which is an additional motivation to keep dhcp scripts as simple as possible and invoke external ones. I suppose that the DHCP-specific variables are only available to the dhcp script itself, but I have never tried that.

As for sending an e-mail when internet fails, not everyone has the luxury of having multiple ISPs active at his location and for prices which allow to pay for two uplinks.
Instead of writing novels, post /export hide-sensitive. Use find&replace in your favourite text editor to systematically replace all occurrences of each public IP address potentially identifying you by a distinctive pattern such as my.public.ip.1.
 
anav
Forum Guru
Forum Guru
Posts: 4606
Joined: Sun Feb 18, 2018 11:28 pm
Location: Nova Scotia, Canada

Re: Hairpin NAT: Is there a simple solution?

Sun Jun 14, 2020 5:38 pm

Well the second script really does not affect the dhcp client at all from what I gather.
It basically states, hey if this link is bound, then put the IP of the lease into the address list (in firewall address lists).
If its not bound then dont.

How would this interfere with the DHCP script that is already there???

Are you saying, its better to put that script in the 'normal' script area?
If so, can it read the dhcp client info and do all the same things from there?
Or are you saying incorporate the second script into the first script.

I think what your are intimating, is that if I put the second one in the normal script area, then I should modify the existing DHCP client list,
to (AN action), such that everytime the ISP changes something, and a new IP and gateway are provided, then go to another (invoke another) script to update the firewall list.
Just not sure how you invoke a script from a script, problem 1, and if you can invoke a script not in the same area, problem 2.
Problem 3 is basically I am scriptophobic ;-)
I'd rather manage rats than software. Follow my advice at your own risk! (Sob & mkx forced me to write that!)
 
Sob
Forum Guru
Forum Guru
Posts: 5590
Joined: Mon Apr 20, 2009 9:11 pm

Re: Hairpin NAT: Is there a simple solution?

Mon Jun 15, 2020 1:32 am

..., editing of a dhcp script lacks the colored syntax check available when editing scripts at other places, ...
You mean Terminal, the one and only place that has it? If your RouterOS has it elsewhere, I want it too! Or perhaps you meant other systems? In any case, colors would be cherry on top, pleasant, but I can easily live without that. Just good old "syntax error at line X", as my first 8-bit computer could do in last century, would be huge improvement. Current "silent death" mode is really bad. And hey, after all, it is another century, so I want "syntax error at line X, column Y". :)

@anav: In this case it's the simplest programming, if you have two simple scripts like these, you can put one after another:
:if ($bound=1) do={
  :log info ("(script 1) Address acquired: ".$"lease-address")
} else={
  :log info "(script 1) Address lost"
}
:if ($bound=1) do={
  :log info ("(script 2) Address acquired: ".$"lease-address")
} else={
  :log info "(script 2) Address lost"
}
Or combine them:
:if ($bound=1) do={
  :log info ("(script 1) Address acquired: ".$"lease-address")
  :log info ("(script 2) Address acquired: ".$"lease-address")
} else={
  :log info "(script 1) Address lost"
  :log info "(script 2) Address lost"
}
Both will work. I'm not sure about external scripts and passing variables to them either. As the whole thing works now (see above), it's not fun to try and explore.
People who quote full posts should be spanked with ethernet cable. Some exceptions for multi-topic threads may apply. Not intended as incentive for masochists.
 
Danielwalton
just joined
Posts: 2
Joined: Tue Jun 16, 2020 5:16 pm
Contact:

Re: Hairpin NAT: Is there a simple solution?

Tue Jun 16, 2020 5:25 pm

wow what a simple answer, explanation!
 
doctorpangloss
just joined
Topic Author
Posts: 5
Joined: Thu Jun 11, 2020 1:07 am

Re: Hairpin NAT: Is there a simple solution?

Tue Jun 16, 2020 7:19 pm

So to get this back on topic, which is sort of illustrative of how needlessly complicated this problem is...

What are the commands to enable hairpin NAT for any and all future possible conventional port forwarding configurations (including those specified by UPnP) for a dynamically assigned IP address and an otherwise conventionally configured router?

I see a very close answer near the top, but I'm still not sure, because without a clear command it's hard for me to test. I really appreciate the help. For users with services in their internal network, especially using hostname-based modern URL routing like I do, this will be the best script you'll author today!
 
faxxe
just joined
Posts: 22
Joined: Wed Dec 12, 2018 1:46 pm

Re: Hairpin NAT: Is there a simple solution?

Tue Jun 16, 2020 7:44 pm

I have 3 services running on an internal server (192.168.1.254) which are also available from WAN.
The port numbers are 443, 8051 and 8888
I can reach them from my LAN with that link (example):
http://<my.domain>:8888

These are the Hairpin NAt entrys:
/ip firewall nat
add action=masquerade chain=srcnat comment="Hairpin Masq" dst-address=\
    192.168.1.0/24 dst-port=8888,8051,443 protocol=tcp src-address=\
    192.168.1.0/24
add action=dst-nat chain=dstnat comment="Hairpin 8888" dst-address-list=\
    external-ip dst-address-type=local dst-port=8888 in-interface=bridge1 \
    protocol=tcp to-addresses=192.168.1.254 to-ports=8888
add action=dst-nat chain=dstnat comment="Hairpin 8051" dst-address-list=\
    external-ip dst-address-type=local dst-port=8051 in-interface=bridge1 \
    protocol=tcp to-addresses=192.168.1.254 to-ports=8051
add action=dst-nat chain=dstnat comment="Hairpin 443" dst-address-list=\
    external-ip dst-address-type=local dst-port=443 in-interface=bridge1 \
    protocol=tcp to-addresses=192.168.1.254 to-ports=443


To get my external, dynamic IP i use this script in DHCP client for my WAN port:
:if ($bound=1) do={
  /ip firewall address-list set [/ip firewall address-list find where comment="wan1ip"] address=$"lease-address" disabled=no
} else={
  /ip firewall address-list set [/ip firewall address-list find where comment="wan1ip"] disabled=yes
}
Works perfect for me even on dynamic WAN ip´s

-faxxe
 
Sob
Forum Guru
Forum Guru
Posts: 5590
Joined: Mon Apr 20, 2009 9:11 pm

Re: Hairpin NAT: Is there a simple solution?

Wed Jun 17, 2020 12:54 am

So to get this back on topic, which is sort of illustrative of how needlessly complicated this problem is...
Required srcnat rule can be just one and it covers all ports (192.168.88.0/24 is LAN subnet):
/ip firewall nat
add chain=srcnat src-address=192.168.88.0/24 dst-address=192.168.88.0/24 action=masquerade
Add it once and you won't have to touch it again. Main problem is how to create dstnat rules:
/ip firewall nat
add chain=dstnat <????> protocol=tcp dst-port=1234 to-addresses=192.168.88.x to-ports=2345
<????> is where you choose how to match destination. You can't use the popular in-interface=<WAN> or in-interface-list=<WANs>, because it wouldn't match connections from LAN. Basic choices are:

a) dst-address=<public address> for static address or scripted updates for dynamic
b) dst-address-list=<list containing public address> for static adddress, scripted updates for dynamic, or automatic resolution using DDNS hostname
c) dst-address-type=local for any address on router, with additional dst-address(-list)=<some addresses to exclude> when you want to dstnat some port to internal server, but also use it on router (e.g. 80 for WebFig)

That's when public address is directly on router. If it's elsewhere (router is behind NAT), you need to look for two different destinations, public address for connections from inside and another for connections from outside. That can be either router's address on WAN interface, or in-interface(-list)=<WAN> would work too, but with that you'd need two separate rules. If you use dst-address-list containing both addresses, it can be done using one rule.

So yes, it may seem kind of complicated, but what can you do, NAT sucks and most of the world ignores the real solution (which is IPv6) for last twenty years.
People who quote full posts should be spanked with ethernet cable. Some exceptions for multi-topic threads may apply. Not intended as incentive for masochists.
 
doctorpangloss
just joined
Topic Author
Posts: 5
Joined: Thu Jun 11, 2020 1:07 am

Re: Hairpin NAT: Is there a simple solution?

Mon Jun 22, 2020 9:29 am

This is really close.

Is there a way where I do not have to create an additional rule for every port? I already have UPnP port forwarding. I would like to somehow make those UPnP forwarding / NAT rules just work with hairpin NAT.
 
Sob
Forum Guru
Forum Guru
Posts: 5590
Joined: Mon Apr 20, 2009 9:11 pm

Re: Hairpin NAT: Is there a simple solution?

Mon Jun 22, 2020 7:43 pm

It depends. I can't test it right now and I don't know what exact rules UPnP creates, but if they have dst-address=<public address on WAN interface> and not in-interface=<WAN>, it should just work.
People who quote full posts should be spanked with ethernet cable. Some exceptions for multi-topic threads may apply. Not intended as incentive for masochists.
 
Sob
Forum Guru
Forum Guru
Posts: 5590
Joined: Mon Apr 20, 2009 9:11 pm

Re: Hairpin NAT: Is there a simple solution?

Tue Jun 23, 2020 3:56 am

Unfortunately, it doesn't look good for UPnP ports. It adds rules like this:
/ip firewall nat
add action=dst-nat chain=dstnat comment="upnp 192.168.80.10: libminiupnpc" dst-address=<public address> dst-port=8080 in-interface=<WAN interface> protocol=tcp to-addresses=192.168.80.10 to-ports=80
The in-interface=<WAN interface> won't match for connections from LAN. I don't really see why it should be there, IMHO dst-address=<public address> alone would be good enough. So maybe you could try to ask MikroTik, it they couldn't get rid of in-interface. Or make it optional.
People who quote full posts should be spanked with ethernet cable. Some exceptions for multi-topic threads may apply. Not intended as incentive for masochists.
 
doctorpangloss
just joined
Topic Author
Posts: 5
Joined: Thu Jun 11, 2020 1:07 am

Re: Hairpin NAT: Is there a simple solution?

Mon Jun 29, 2020 11:28 pm

Okay, this is some very good progress, I really appreciate how clear you've been.

Yes, I see results like that. Different UPNP clients add different comments, but otherwise the rest is controlled by MicroTik's implementation.

Alternatively, if there is a better standard for remotely configuring port forwarding on a router that I am not aware of but that MicroTik supports, which optionally supports hairpin NAT, that may be what we're looking for.

Perhaps a script which rewrites upnp rules is what I'd need? In other words, on a frequently schedule, iterate through every existing NAT rule. If the comment starts with upnp and does not contain the hairpin NAT decoration, modify/decorate the rule to support hairpin NAT.
 
Sob
Forum Guru
Forum Guru
Posts: 5590
Joined: Mon Apr 20, 2009 9:11 pm

Re: Hairpin NAT: Is there a simple solution?

Tue Jun 30, 2020 1:02 am

UPnP would work great, if MikroTik didn't add in-interface to created rules. Other standards wouldn't help, if they did the same with them. Not that there's much to choose from and RouterOS currently doesn't have anything else.

Script to periodically check existing UPnP rules and create/remove same rules, only without in-interface, could be a solution. I wouldn't like it at all, because every time this approach is used, you have to choose if you're going to run it less frequently and have all changes lagging behing, or run it very frequently and unnecessarily load the router, which is not good, especially when you know that actual changes don't happen often.
People who quote full posts should be spanked with ethernet cable. Some exceptions for multi-topic threads may apply. Not intended as incentive for masochists.

Who is online

Users browsing this forum: BillyVan, eworm, keithy, prozak and 63 guests