1:1 NAT on the same interface results in unexpected source IP

Started by tars21, October 24, 2023, 02:31:11 PM

Previous topic - Next topic
Hello everyone

Environment:

  • OPNsense 23.4.2_1-amd64
  • Primary / Secondary High Availability Setup
  • 20+ Interfaces
  • 8 physical interfaces for internal traffic, multiple VLANs
  • single WAN interface

We have the following One-to-One NAT rule (example IPs)
Interface: WAN
Type: BINAT
External network: 93.10.10.10/32
Source/Internal IP: 10.10.10.1/32
Destination: any (also tried with specified Interface)
NAT reflection: Enable


If any host that is not on the same network tries to accesses this external IP address, it will be forwarded accordingly and can access it correctly. The expected source IP can be seen in the tcpdump and access.log.

However, if a host on the same network ( source and destination are on the same interface ) accesses the external address, the source IP address varies between 3 addresses alternately:

  • 10.10.10.1 (CARP IP of Interface)
  • 10.10.10.2 (Interface IP of primary firewall)
  • 10.10.10.17 (IP Alias on the Interface, used by HAProxy)
The actual source IP address of the internal Host does not appear in this scenario.
The connection works and data exchange is possible. But my expectation would be to see the correct source IP address here.

The workaround to communicate directly via the internal IP address unfortunately does not work in our scenario.

Do you see the error in our setup? I would be very happy about any hints!
Many thanks in advance.

That is because when there is NAT Reflection/Hairpin, and the Host and Client are in the same subnet/VLAN, the firewall has to redirect the communication with its own IP address back to the client.

Otherwise there would be asymmetric TCP traffic, because the client would use their arp table to communicate directly with the server after the initial request to the firewall.

I wrote a doc that goes into this in detail: https://docs.opnsense.org/manual/how-tos/nat_reflection.html

Hardware:
DEC740

Thank you for your quick reply. I will schedule time for your documentation and go through the setup again with it.

Great, if you have any specific questions just post here again and I will answer them when I have time.  :)
Hardware:
DEC740

Sorry for my late reply: With the implementation based on your instructions (thank you again), the NAT hairpin now looks like this: I only find one IP address instead of the alternating three IP addresses in the access.log. The sender is now always 10.10.10.1 (the CARP interface IP).
This is probably exactly as it is written in your instructions: "rewrite the source ip to 172.16.1.254 (DMZ address) and [...]".

Is this exactly how NAT Hairpin works? The sender IP address - in this scenario - is never the actual IP address, there is always a translation to the interface IP?