Im feeling lazy so I will make it short................
Hairpin Nat is a funny situation of dst-nat and mostly for the case of port forwarding, where the requirement needs to address local users as follows:
a. The server and the lan users of the server ar
e on the same subnet
b. The server admin requires access to the server via its domain name (external WANIP).
a. 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.
b. The admin for other reasons does not want users to use the LANIP address of the servers.
Two quick ways to avoid the need for Hairpin NAT include:
i. Simply move the lan users or Server to a different subnet, done!
ii. Allow the lan users to use the LANIP of the server for access, done!
If the two options are not to your liking then we have to adjust the config of the Mikrotik appliance and there are two main approaches, one touching upon DNS changes and the other various manipulations of dst-nat rules and one necessary src-nat rule.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Scenario: Server IP is 192.168.88.68, protocol tcp, port 12566, WANIP=47.123.12.89 (if static), domain name=
www.myserver.net
(1) DNS METHOD – REDIRECT LAN REQUEST VIA DNS (courtesy of rextended & ZeroByte)
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
c. others...
This rule will capture any request for DNS when looking for that domain name and direct the query to the server IP.
However, some users on the same subnet may have DNS hard coded on their PCs...... and thus you need to redirect all DNS queries to the router to handle.
add action=redirect chain=dstnat comment="Force Users to Router for DNS - TCP" \
dst-port=53 protocol=tcp src-address=192.168.88.0/24
add action=redirect chain=dstnat comment="Force Users to Router for DNS - UDP" \
dst-port=53 protocol=udp src-address=192.168.88.0/24
This should effectively ensure that regardless of PC DNS settings, all the queries from the subnet will go through the router and thus hit the static DNS rule created.
Two important points:
(i) You'd need to make sure "allow remote request" is turned on in /IP DNS, and
(ii) *BE SURE* that your input firewall filter blocks DNS requests from the Internet itself so that you don't get this router taken over by a dns-amp ddos attack. This is not normally a concern if you are using the default firewall rules or any substitution thereof with a drop all else rule.
(2) MANIPULATING NAT
First Step: SOURCE-NAT APPROACH (
May be all you need!)
In all cases (dynamic or static WANIPs) the first step that is consistent across all variations of manipulating NAT, is the addition of a source-nat rule addition placed before the default SRC-NAT rule.
add chain=srcnat action=masquerade dst-address=192.168.88.0/24 src-address=192.168.88.0
This rule effectively addresses the discrepancy when the router intercepts the return traffic from the server and ignores the WANIP NAT tracking because it knows the originator was local on the router and thus tries to send the traffic directly back to the originator via its LANIP totally befuddling the NAT engine. The rule ‘approves’ the direct return of traffic from the server to the originator for NAT engine purposes even though the request seemingly came from the WAN.
Static WANIP configurations, with this SRC-NAT rule in place, do not require any changes to any existing DST-NAT RULES (format as follows):
add chain=dstnat action=dst-nat dst-address=47.123.12.89 dst-port=12566 \
protocol= tcp to-addresses=192.168.88.68 {to-ports only required for port translation}
Second Step (if needed): ALL other variations address Dynamic WANIP configurations and boil down to replacing or mimicking the dst-address=WANIP with something similar.
(2a) Dynamic WANIP Local Address approach (kudos to ?????)
This method is fairly straight forward in that you tell the router to use a local address as the destination address but to not use the subnet the server (and users) are on. Effectively the router will choose the next available local address and it should be the current WANIP.
add chain=dstnat action=dst-nat dst-address-type=local dst-address=!192.168.66.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.
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
Add ip=othersubnetA list=allsubnets
Add ip=othersubnetB list=allsubnets
Etc.
(2b) Dynamic WANIP Approach using Firewall Address List and IP Cloud (kudos to Steveocee)
This method relies upon using ones IP Cloud IP address as a firewall address list entry. The IP Cloud function periodically updates the WANIP every ???? minutes. Instead of using dst-address=WANIP one uses dst-address-list=updatedCloudIP
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:
(i) Best when there is 1:1 NAT or
(ii) 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.
(2c) Dynamic WANIP approach using a Firewall Address List and IP DHCP Client related script (most elegant and courtesy of Sob (sos??))
This method utilized a script that pulls the actual WANIP from your IP DHCP Client settings. The script allows the admin to set any schedule desired vice the fixed IP cloud updates.
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.