I have a VM in an Azure VNet that needs to know the original public IP address of incoming connections that are port forwarded by a firewall appliance. So far I can only successfully port forward from the firewall to the server if I "SNAT" the incoming connection. But that hides the original source IP.
Here is a simplification of the current design
Firewall has single interface of 10.0.0.1 which is associated with a public IP in Azure. Port forwarding is configured on firewall to send any TCP 80 to server 10.0.1.1 following logic as outlined in this blog Client connects to public IP address. Logs on firewall show approved data from IP 184.108.40.206 -> 10.0.0.1. If outbound NAT is configured on the firewall to translate the connection after port forwarding, the server (10.0.1.1) shows the connection, but the source IP = 10.0.0.1 (ie the private interface of the FW)
If outbound NAT translation is disabled on the FW appliance, the logs show the same approved information on the FW for an incoming connection, but the packet never reaches the 10.0.1.1 sever.
If I stand up a second server 10.0.1.2 or 10.0.0.2 and then connect to 10.0.0.1:80 (with outbound NAT translation disabled on the FW appliance) then the connection makes it successfully though to to server 10.0.1.1 and the src IP correctly equals 10.0.1.2 or 10.0.0.2
I suspect the Azure fabric routing is dropping any packets where any src IP is not within the range of the VNet address space. There are plenty of online articles showing a similar "DMZ" style approach like this in Azure, but none where the request handling servers need to know the original public source IP address.
Can it be done ?
After fighting with this all day I could not get it to work. So I've dropped the FW and recreated another applicance with 2 NICs. The original NIC (the WAN) as it was before and the other in the 10.0.1.1 subnet (the LAN). BUT IT STILL FAILS TO WORK! I cant even get a connection...
I have a replicated the same setup in my office on some bare metal and it works perfectly. I've checked all the FW settings (including routes) between the bare metal instance and the azure instance. I've run a packet capture on the LAN interface of the azure instance and can see the "port forwarded" packets leaving the interface. I have Wireshark running on 10.0.1.1 but no packets ever arrive! I thought it might be a default gateway problem so I added a user defined route to the 10.0.1.0 subnet for network 220.127.116.11/32 to make sure the ACK's would return to the client via the FW appliance. But that did not work either.
Any other help would be very much appreciated, this one has be busted.
Many hours and VM's later I've got it to work. The problem was the user defined route on the 10.0.1.x network. I had only enabled a route to cover the range of the clients connecting but that did not work. If I set the UDR = 0.0.0.0/0 and next hop to the FW appliance, then bingo.
So to summise my working config.
- pfSense firewall with one NIC
- NIC in 10.0.0.x network with public IP also associated
- No outbound NAT mappings defined
- Port forward rule from client IP:port to server in 10.0.1.x network
- User defined rule of 0.0.0.0/0 set on 10.0.1.x network with next hop = private ip of NIC on FW
- IP forwarding enabled on the FW NIC
Whilst the above now passes the client IP all the way through to the VM in the 10.0.1.x network and allows a successful connection, I did add an outbound NAT mapping of 10.0.1.x/24 so the VM can access the internet. Without it, it could not. The UDR also kills any access via a public IP attached to the VM in the 10.0.1.x network and additional rules are now needed on the FW to allow RDP etc to the VM via the FW.
For anyone's benefit, I also got the two NIC FW working too. Here the UDR just needs to point to the IP of the 'LAN' NIC.