This is kind of a special scenario but actually occured for me. A port on the pfSense WAN should be NAT:ed to an IP-address located on a remote subnet via an ipsec tunnel. The problem here was the router on the other end of the tunnel did not route all it’s outgoing traffic over the tunnel. Only a few subnets behind the pfSense went through the tunnel. All other traffic was using the routers normal Internet connection.
In the image above, a port (123 in the example code below) on the pfSense (18.104.22.168) should be NAT:ed and port forwarded to 10.0.0.7. The result was the NAT:ed port forwarded packets reached the intended host (10.0.0.7) but replies probably went straight back on the internet, not going back through the tunnel.
I solved this by setting up a simple proxy on a server using iptables located on a machine in one of the subnets at the pfSense site which was reachable from 10.0.0.7 through the tunnel. See next image.
The proxy was made using iptables in a Ubuntu machine on 10.2.2.2. Both the proxy server on 10.2.2.2 and the host 10.0.0.7 could reach each other over the ipsec tunnel.
In pfSense I changed the NAT / port forward of port 123 from 10.0.0.7 to 10.2.2.2 (and deleted the existing states in pfsense from my previous tries, until I did that, this didn’t work).
The proxy server using IP-tables was set up like this (guide found here):
sudo sysctl -w net.ipv4.ip_forward=1 sudo iptables -t nat -A PREROUTING -i ens160 -p udp --dport 123 -j DNAT --to 10.0.0.7 sudo iptables -t nat -A POSTROUTING -o ens160 -p udp --dport 123 -j SNAT --to-source 10.2.2.2 sudo iptables -t nat -A POSTROUTING -p udp --sport 123 -j SNAT --to-source 10.2.2.2
You will probably want to make sysctl ip_forward and iptables statements persistent over reboots.