Port Forwarding can fail and some of the common solutions are discussed......... (thanks to Sob for his support on this article)
This article is meant to mainly discuss both the often tripped over Hairpin NAT scenario and the extra work required to deal with a dynamic WANIP in conjunction with destination NAT.
Caution: Issues with port forwarding may indicate you do NOT have a PUBLIC IP! Are you on LTE If so jump to item 5.
Note: If you want to simply check your basic Port Forwarding associated rules/format - JUMP to item 6.
Intro: Hairpin NAT
1. Adding Source-NAT Rule (Hairpin NAT) - solutions for static, dynamic WANIPs
2. Changing Subnet of Server (avoiding Hairpin NAT)
3. DNS Method (avoiding Hairpin NAT)
4. Multiple Destination NATs & Jump (for static WAN IPs)
5. Public IP - Are you Sure?
6. NAT & IP Firewall Rules
7. Source & Destination NAT Simplified
8. Adguard / PiHole
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HAIRPIN NAT INTRO
Unable to access your server via the DOMAIN name from the LAN??? <-------- @dhanushka
Easily solved but every person will have to decide what is the optimal way to configure their device(s) for hairpin NAT (sometimes called Loopback).
INTRO: Hairpin NAT is a funny situation of what is often incorrectly considered a dst-nat problem/variation for the case of port forwarding, (and its really a source-nat issue) where the use case describes a server on a local subnet and the local users on that subnet, as follows:
a. The server and the LAN users of the server are on the same subnet
b. The server admin requires that access to the server is provided via its domain name (external WAN IP).
i. This could be for several reasons but for example when one has multiple vlans and a standard method for access is provided that works for all users, regardless of vlan associated forward chain firewall rules.
ii. The admin for other reasons does not want users to use the LANIP address of the servers.
iii. {Leave blank for other reasons.}
There is one quick work around - Let your LAN users use the LANIP of the server!!!
If the simple work-around option is not a feasible alternative then we have to adjust the config of the Mikrotik appliance and there is one main approach dealing with Source NAT, and two other discussed options that use an approach to bypass the issue, one touching upon DNS changes and the other involves moving the Server to a different subnet. The main solution consists of using one necessary src-nat rule and various manipulations of dst-nat rules in case one's WANIP is dynamic ( properly configured fixed/static WANIP dst nat rules are already good to go). All solutions work, it depends on your particular configuration and your level of comfort in modifying the configuration. If coming from other vendors, this scenario was often handled by a simple check in a check box labelled "LOOPBACK".
RELEVANT SCENARIO INFORMATION FOR EXAMPLES
Server IP is 192.168.88.68, protocol tcp, port 12566,
WANIP=47.123.12.89 (for static examples), domain name=www.myserver.net
WANIP=dynamicIP (for dynamic examples) domain name=www.myserver.net
Alternate LAN subnet server IP192.168.50.5
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1. ADDING SOURCE-NAT RULE (HAIRPIN)
To fix the scenario where the LAN users and the Server are on the same subnet, all that is required is the following generic source NAT rule, often called the HAIRPIN NAT Rule placed as the first source NAT rule (although I have been told order here is not important). This required source NAT rule is independent of the type of WANIP (static/dynamic).
The key addition to the NAT rules is the addition of a source-nat rule placed before the default src-nat rule (substitute with your server subnet).
add chain=srcnat action=masquerade dst-address=192.168.88.0/24 src-address=192.168.88.0/24
Courtesy of Sob, (the problem):
"- user client 192.168.88.5 wants to connect to www.myserver.net, resolves hostname, gets 47.123.12.89 and sends initial packet to it
- client doesn't have any idea where 47.123.12.89 is, as far as it knows, it can be on the other side of planet
- dstnat rule changes packet's destination address to 192.168.88.68 and sends it to server
- source address is not changed, it's still 192.168.88.5 <- the problem
- server gets the packet and sends response directly to 192.168.88.5, because it's in same subnet!!
- client throws it away, because it doesn't expect any response from 192.168.88.68
the client is expecting a response from 47.xx
WHY this additional SRC NAT rule works: When the client sends the outgoing request now two things happen, the first thing is as before the destination NAT rule will change the destination from that resolved to the WANIP 47.xx to that of the Server .68, and now additionally, the outgoing traffic also gets masqueraded gets 'natted' to the subnet gateway address. Therefore the traffic is now headed to the Server with source IP address of the gateway of the subnet (vice the client). Then when the server replies to the traffic it sends the traffic back to the router as what it sees now as the source (originator of the traffic) is the IP 192.168.88.1. The router tracking the packets then applies the dst-nat rules and masquerade rules recognizing the returned traffic and thus un dst-nats the traffic from dst of 192.168.88.86 back to original dest of 47.xx and un-source nats the traffic from 192.168.88.1 to the original 192.168.88.5 and the packet arrives at the client and is accepted.
The explanation diagrams found here may be helpful(courtesy of Greg) : http://gregsowell.com/?p=4242
Finally this explanation on hairpin nat from MKX is invaluable!!
Standard SRC-NAT is masquerading source address and standard DST-NAT is masquerading destination address. And hairpin NAT is masquerading both addresses, one to each end (client doesn't use the correct dst-address and server doesn't see correct src-address).
Usual hair-pin NAT (in typical port forwarding) makes sure that the LAN client can talk to LAN server via some foreign (to both client and server) IP address, in the case of masquerading (redirecting) WANIPs, then the case becomes the WAN client talking to LAN server via some foreign (to both client and server) IP address (and that communication needs to pass router in both directions). Remember that any of the router's own IP addresses are treated equally regardless of ingress interface of a particular packet
- e.g packet targeting router's WAN IP address, ingressing through LAN interface is treated the same way as packet targeting same IP address ingressing through WAN interface.
Finally if you want to read the explanation of how using hairpin nat addresses a similar situation where the WANIP needs to be 'fixed' using source-nat (hairpin technique) for a particular scenario, look at this post! ( example of WAN Client talking to LAN server )
viewtopic.php?p=921962#p919200
A. STATIC-FIXED WAN IP.
With the above rule in place and the CORRECT DST NAT rule for static WANIPs is utilized, the router will now handle both the 'normal' external incoming requests as well as internal server requests via the dst NAT rule.
add action=dst-nat chain=dstnat dst-address=47.123.12.89 dst-port=12566 protocol=tcp to=addresses=192.168.88.68
B. DYNAMIC WANIP
Dynamic WANIP is an issue because we cannot use the DST-ADDRESS=WANIP part of the configuration due to the fact that the IP can change (hence dynamic). Most iterations of dynamic WANIP attempt to solve this particular issue. The problem is exacerbated by the fact that the often used default DSTNAT rule for dynamic WAN with in-interface-list=WAN or in-interface=eth1 will not work for internal LAN users. Using in-interface list=WAN, quite clearly excludes LAN users from the equation as they are NOT coming from the WAN interface. The following methods, shown below, attempt to address this problem by using techniques to mimic the fixed/static IP addressing standard in order to identify the current WAN interface. In other words, the admin wants to include both external and internal users by acknowledging the destination of both these groups is the current WANIP. We have to do this without using in-interface-list=LAN OR in-interface=eth1.
(i) ]DYNAMIC WAN IP Local Address approach
This method is fairly straight forward in that you config the router to use a local address as the destination address, but then deny the local subnet address to the router as an option. Effectively one is attempting to match any local interface that is not excluded. In a one subnet LAN, that leaves only the WAN interface as the only available local address for destination, success achieved. The reason we dont simply state =local address, is due to the fact that any other request on port 12566, unrelated to the server would be forwarded to the server. Not necessarily an issue with an obscure port but would be problematic lets say on port 80.
add chain=dstnat action=dst-nat dst-address-type=local dst-address=!192.168.88.1 \
protocol=tcp dst-port=12566 to-addresses=192.168.88.68
Limitations: This rule ONLY suffices for a single subnet structure behind the Router. As soon as you add more subnets/vlans the rule gets more complex and one would then have to use a firewall address list to identify all subnets on the network that should not be considered as a local subnet to force the router to choose the only remaining available local address, which then would be the WAN interface.
Add chain=dstnat action=dst-nat dst-address-type=local dst-address-list=!allsubnets \
protocol=tcp dst-port=12566 to-addresses=192.168.88.68
Where:
Add ip=subnetofserver list=allsubnets (contains users and server)
Add ip=othersubnetA list=allsubnets (contains users)
Add ip=othersubnetB list=allsubnets (contains users)
Etc.
(ii) DYNAMIC WAN IP - Firewall Address List and IP Cloud (kudos to Steveocee) ALSO GOOD FOR ANY DYNDNS URL APPROACH
This method relies upon using ones IP Cloud IP address as a firewall address list entry to replace the actual dst-address of the router. The IP Cloud function periodically updates the WAN IP every few minutes. Thus, instead of using dst-address=WAN IP one uses dst-address-list=updatedCloudIP
add chain=dstnat action=dst-nat dst-address-list=updatedCloudIP address protocol=tcp dst-port=12566 to-addresses=192.168.88.68
See https://www.youtube.com/watch?v=_kw_bQyX-3U&t=257s for an excellent presentation.
Limitations: There is a chance of a gap in correct coverage if the WANIP is changed or whatever reason in between IP Cloud updates.
Advantages:
a. Best when there is 1:1 NAT; OR
b. if the router itself doesn’t have a public IP address as the IP Cloud service will provide the correct public IP in front of your router.
(iii) DYNAMIC WAN IP - Firewall Address List and IP DHCP Client related script (most elegant and courtesy of Sob (still kicken!))
This method utilizes a script that pulls the actual WAN IP from your IP DHCP Client settings. The script also is not schedule dependent, vice the IP cloud updates method.
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
}
Where,
/ip firewall address-list
add comment=wan1ip disabled=yes list=external_wan
Limitations: Not suited for a private WANIP setup.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AVOIDING HAIRPIN NAT RULE
2. CHANGING SUBNET OF SERVER
In this scenario, there is no requirement for a sourcenat rule addition as our effort is aimed at avoiding hairpin natting! In fact, there is no hairpin required because the server and users are now on a different subnet, HOWEVER, one has to ensure a properly formatted DST-NAT rule for the dynamic WANIP setup.
a. Fixed IP Static......... the standard DST-NAT rule will suffice.
add action=dst-nat chain=dstnat dst-address=47.123.12.89 dst-port=12566 protocol=tcp to=addresses=192.168.88.68
b. Dynamic WANIP.............
In this case the standard default dynamic dst nat rule will NOT work.
add action=dst-nat chain=dstnat in-interface-list=WAN or in-interface=eth1-WAN dst-port=12566 protocol=tcp to=addresses=192.168.88.68
INSTEAD
use one of the techniques listed abovefor dynamic WANIP
(1)B. (i), (ii), (iii)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3. DNS METHOD - AVOID NAT – REDIRECT LAN REQUEST VIA DNS (courtesy of rextended & ZeroByte)
Similar to moving the Server to a different subnet, using DNS tricks also avoids hairpin NAT.
Create the following rule!
/ip dns static
add address=192.168.88.68 regexp="(^|www\\.)myserver\\.net\$" ttl=5m
The precedence for using DNS within the router is as follows...........
a. static first,
b. static regexp next, and
c. others...
This rule tells the router that for any DNS traffic that is generated to look for the domain name www.myserver.net location, there is no need to go to dynamic servers, cached servers, external internet internet servers etc., go directly to the location of the LAN IP indicated (our Server).
Two Points and One Reminder:
(i) You'd need to make sure "allow remote request" is turned on in /IP DNS,
(ii) Ensure there are no static entries in DNS as they take precedence, and
(iii) Confirm you are using default firewall rules and specifically on the input chain, the drop all from the WAN rule:
add action=drop chain=input comment="defconf: drop all not coming from LAN" \
in-interface-list=!LAN
OR the common replacement, as the last rule in the input chain:
add action=drop chain=input comment="drop all else"
Not really a concern with a decent firewall but in general we want to ensure that DNS requests from the internet are blocked to avoid dns-amp ddos attack etc...
One could consider invoking a raw rule dropping all DNS queries from the WAN side.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
That concludes hopefully a more full discussion of the reasons for Hairpin NAT and the options available to tackle this issue depending upon type of WAN connectivity.
Any suggestions comments additions welcome.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4. (OTHER) FIXED WANIP - MANY DST NAT RULES - USE OF JUMP. (Courtesy of Sob)
When dealing with a static IP there is a way to be more efficient with the rule set and this efficiency is also useful in case the Fixed IP changes for whatever reason.
Here is an example of how to setup JUMP rules such that the one rule is checked for WANIP only. One can intuitively see that if the IP ever changes, one only has to modify one IP address entry for potentially a long list of dst-nat rules. SWEET!
/ip firewall nat
add chain=dstnat dst-address=1.2.3.4 action=jump jump-target=port-forward
add chain=port-forward protocol=tcp dst-port=443 action=dst-nat to-addresses=192.168.1.10
add chain=port-forward protocol=tcp dst-port=3389 action=dst-nat to-addresses=192.168.10.33
...
add chain=port-forward protocol=tcp dst-port=25 action=dst-nat to-addresses=192.168.20.13
5. PUBLIC IP? Before tripping over hairpin NAT it is common to discover that an admins issue is the fact their public IP or so they thought is not all the public.
1) Do you know what is a public address?
2) Do you have public address? CGNAT ( aka LTE variety or STARLINK is NOT a public IP! }
3) Check with the ISP that they are not blocking ports (udp, tcp etc)
USING LTE WITH APN..........
Ensure you have a custom APN , ( not the default network APN ) from the ISP provider, which enables a Public IP!!
Checking What Your IP IS:
In other words, the admin should ensure that the WANIP the router gets is the same one that the external World sees. This can be accomplished via
a. 'whats my IP' in your browser
b. Checking the public IP that shows up when one enables IP Cloud.
c. Checking what IP address is shown under the details of IP DHCP Client
d. Checking what IP address is shown in IP routes - look for a (DAC) entry and preferred source.
They should ALL be the same if your router is getting a valid Public IP. If not, then you may be getting a private IP address from your Provider.
If the public IP is clearly not public...........
i. Call your ISP tech support and describe the issue with your WANIP addressing. It could be a misconfiguration at their end!
ii. If not a misconfiguration, ask tech support if you can get a PUBLIC IP.
iii. Ask tech support if it is possible for you to access the ISP modem/router (many do for the exact purposes of forwarding ports etc..)
iv. If you already have a password to access the ISP modem router, try to access the ISP modem/router and port forward the port needed for your server, to the WANIP of your router (a LANIP on the ISP device's subnet).
TROUBLESHOOTING BY LOGGING:
Simple.
To get a sense of what is happening with your external originated traffic you can use logging to track if traffic is reaching the router and try some online port tester and any port.
/ip firewall mangle
add chain=prerouting in-interface=<WAN> connection-state=new action=log log-prefix=INCOMING (if you have a specific dst-port and protocol include those as well)
And you need to be testing this from internet, not from device in same LAN (once it works from internet, it's possible to make it work from LAN too, but requires additional config). This will be useful information when you come to the forum for assistance.
Complex. - viewtopic.php?p=963756#p963756 (courtesy of Sob)
/ip firewall mangle
add chain=prerouting connection-mark=debug-pf action=log log-prefix=port-forward
add chain=prerouting connection-state=new src-address=<local PC address> dst-address=<public address> protocol=tcp dst-port=443 action=mark-connection new-connection-mark=debug-pf log=yes log-prefix=port-forward-NEW passthrough=yes
add chain=forward connection-mark=debug-pf action=log log-prefix=port-forward
add chain=postrouting connection-mark=debug-pf action=log log-prefix=port-forward
6. NAT AND IP FIREWALL RULES ---> normally consists of three rules.
For basic destination nat which includes basic port forwarding, if coming from other devices, one needs ONE firewall rule in the forward firewall filter chain. The rule (example below) basically allows port forwarding to a server on the LAN, that has a corresponding DST NAT rule in the config. Then you need DST-NAT rules fore every port forwarding, each with all the details. A source nat rule is a more general rule so that any traffic initiated by the LAN is natted by the Routers WANIP on the way out. Thus source-nat is important only if local users are directed to the server (not through LANIP) but through the WANIP.
a. Filter Rule: add chain=forward action=accept connection-nat-state=dstnat
{ any traffic with destination ports identified in DST NAT rules will be allowed through firewall }
b. Source Nat Rule:
case1: Dynamic WANIP add chain=srcnat action=masquerade out-interface-list=WAN { will also work for fixed/static WANIPs but not as technically correct }
case2: Fixed/Static WANIP add chain=srcnat action=src-nat out-interface=ether1 to-addresses=WANIP(static) { where out interface must be the active interface, pppoe1-out, vlan etc. }
c. Destination Nat Rule:
case1: Dynamic WANIP add chain=dstnat action=dst-nat dst-port=xxxx protocol=yyy in-interface-list=WAN \
to-addresses=IPof Server { to ports not required if same as dst-ports }
case2: Fixed Static WANIP add chain=dstnat action=dst-nat dst-address=WANIP(static) dst-port=xxxx \
protocol=yyy to-addresses=IPofServer to-ports=zzzz { in this case users come in on port xxxx but the port gets translated to zzzz before hitting the server }
c. Destination Port Ranges: Caution, ensure port ranges do NOT overlap with expected incoming VPN listenting ports as DST nat takes precedence over input chain rules.
7. SOURCE NAT & DESTINATION NAT SIMPLIFIED (courtesy of sob)
Masquerade is special kind of srcnat that automatically chooses source address, the one which is on outgoing interface. So if there's really just one, there's no problem, but if for some reason there are more, it may not choose the one you want. Then you'd need action=src-nat and choose one yourself. Even if you have only one, you can still use action=src-nat to-addresses=192.168.88.1.
If you have out-interface=ether1, it's just one of possible conditions, it's not linked to masquerade choosing address from outgoing interface. Masquerade will always do that, even if the rule is just:
/ip firewall nat
add chain=srcnat action=masquerade
SRCNAT changes source addresses and/or ports, DSTNAT changes destination addresses and/or ports. And it can be anything to anything. Most common is private addresses to public address (to access internet), but you can do any other translation you can imagine. Some will make sense and do something useful, some won't. Instead of translating your internal private addresses to your public one, you can translate them to some other private address(es), some public address(es) you don't even have, anything. Router will be happy to do it for you. Only it won't do you any good, because you won't be able to connect to anything with resulting invalid source address.
As for masquerade, let's say you have simple router with few interfaces:
- WAN with public address 1.2.3.4
- LAN1 with 192.168.88.1/24
- LAN2 with 192.168.99.1/24
- VPN with 10.20.30.40/8
If packet goes out via WAN, masquerade will use 1.2.3.4 as source, for LAN1 it will be 192.168.88.1, for LAN2 192.168.99.1, for VPN 10.20.30.40. In short, whatever is on outgoing interface.
8. Adguard / PiHole - Directing Users to Servers on LAN Subnet. (courtesy of sob)
A typical situation where one wants to ensure users are using the admin provided DNS or other server vice a typical server. The one slight twist is that for users within the same subnet of the Server, hairpin nat, just like in the case of generic servers where folks get to the server via the WANIP, also applies here where users are attempting to reach 8.8.8.8 for example but are redirected back to adguard.
In general one needs to ensure that users have access to DNS services in the input chain, if for nothing else, the Adguard/PiHole server and for any users not being directed. In addition all the users need access in the forward chain to the admin provided DNS/adguard server. The next step is to highlight the dhcp-server network settings such that the adguard/pihole IP is used where applicable (in all subnets the admin wants to force traffic to DNS/adguard with one exception). In the case of the subnet the DNS/adguard server is in, simply use the gateway of the subnet. Almost the last step are dst-nat rules to force/redirect users to the Adguar/PiHole just in case they may have IPV4 DNS settings on devices that are different. Finally, one needs to use a hairpin source nat rule for the users in the same subnet as the server.
Note: This will not prevent users that are technically savvy to use DoH to get buy such configurations. Suggest another form of discipline for these cases.

Example: VLANS 10,20,30,40,50 and they all belong to the interface list of LAN.
- Vlan 50 contains adguard/dns server on 192.168.50.50,
- Vlan 20 needs to use regular DNS from router
- Firewall address list called "excluded" includes 192.168.20.0/24 AND 192.168.50.50
Step 1.
/ip dhcp-server network
add address=192.168.10.0/24 gateway=192.168.10.1 dns-server=192.168.50.50
add address=192.168.20.0/24 gateway=192.168.20.1 dns-server=192.168.20.1
add address=192.168.30.0/24 gateway=192.168.30.1 dns-server=192.168.50.50
add address=192.168.40.0/24 gateway=192.168.40.1 dns-server=192.168.50.50
add address=192.168.50.0/24 gateway=192.168.50.1 dns-server=192.168.50.1
Step2.
input chain rules.
add chain=input action=accept in-interface-list=LAN dst-port=53 protocol=tcp
add chain=input action=accept in-interface-list=LAN dst-port=53 protocol=udp
forward chain rules
add chain=forward action=accept in-interface-list=LAN dst-address=192.168.50.50
Step3.
Dst Nat rules
add chain=dstnat action=dst-nat in-interface-list=LAN src-address-list=!excluded dst-port=53 protocol=tcp to-addresses=192.168.50.50
add chain=dstnat action=dst-nat in-interface-list=LAN src-address-list=!excluded dst-port=53 protocol=udp to-addresses=192.168.50.50
Step4.
Src Nat Hairpin Rule for Server Subnet users
add chain=srcnat action=masquerade dst-address=192.168.50.0/24 src-address=192.168.50.0/24
Note: You can be more specific and make it two rules (tcp, udp) and specific to the port if desired.