dnat from 2 inet ports to 1 internal host?
Tue, 29 May 2001 22:09:57 -0400
> I think that it simply doesn't work the way they said. I just had an
> email from Sascha explaining how it works but the explanation did not
> convince me. He was talking about two internal networks and one ISP
> connection which is a totally different picture.
That truly is a different setup and there should be no problem with DNATing
that arrangement. The default route from either internal host would send the
response packet out the ISP interface.
This is how I believe the packets travel through the kernel, route and iptable
code. I have not looked into the code to verify this. It has mainly been my
experience by trial and error.
Incoming packet from interface from ISP.
1. The incoming packet goes to the nat table PREROUTING chain and gets
DNATed. The destination IP address gets rewritten to an internal host.
2. The routing decision is made. Internal destination, so it goes out the internal
3. The packet goes through the filter table FORWARD chain. Here iptables lets
the packet go through to the internal interface. Sends the packet on its way.
Response from the internal host
1. The internal host sends the response back to the firewall. Most likely by its
2. The routing decision is made. By default the routing decision is made on the
destination IP address. In this case it most likely chooses the default route.
At this point the packet still has an internal source IP address.
3. The packet is SNATed. The source IP address is changed back to the address
the packet came in one. This, I believe is handled automatically by the DNAT rule.
Now the packet has an external source IP address.
4. The packet is sent out the interface chosen during the routing decision.
Now this means that the packet will be sent out the interface that is the default route.
This is not necessarily the interface the request came in on. Asynchronies routing would
occur and most likely your other ISP would drop the packet since its source IP address
is not from its network.
To get the response to go back out the interface it came in own I had to do two things.
Well actually three.
1. Add another address to the internal host(s).
2. Add a policy routing rule that says if the source address is the extra internal
the route via a specific ISP (interface).
3. Make sure whatever services are listening on the internal host, listen on both internal
addresses. Most things will listen on all interfaces the service finds at startup.
times you may have to do this explicitly.
Doing this I can make sure any request coming in from one external interface the response
goes back out the same interface.
184.108.40.206 (ISP1, eth1) 220.127.116.11 (ISP2, eth2)
default route via eth1
(internal network, eth0)
(192.168.1.10, 192.168.1.20, eth0)
default route via eth0
Semi-real life example from the above diagram:
1. client: request from 18.104.22.168 -> 22.214.171.124
2. firewall: request comes in interface eth2.
3. firewall: send packet through net table PREROUTING chain.
rewrite destination IP to internal 126.96.36.199 address.
4. Make routing decision based on destination IP address. Since the
destination address is 192.168.1.20, send out interface eth0.
5. firewall: send packet to filter table FORWARD chain. Get approval
to send packet out eth0.
6. internal host: Get a request to 192.168.1.20 from 188.8.131.52.
7. internal host: Send response back to 184.108.40.206 from 192.168.1.20.
8. internal host: Route via default gateway.
9. firewall: Receive request from 192.168.1.20 to 220.127.116.11.
10. firewall: Packet does not go through may iptable because it is
an ip_conntrack(ed) connection. OK to send out because it was
11. firewall: Route response based on 192.168.1.20 -> 18.104.22.168 addresses.
12. firewall: A policy routing rule is triggered based on source 192.168.1.20.
and route is made via (eth2).
13. firewall: The packet is now unDNATed (SNATed) and the source address
is changed from 192.168.1.20 to 22.214.171.124.
14. client: Receives response from 126.96.36.199 to 188.8.131.52.
>From experience this is what seems to happen. If this info is indeed correct, I think it
to be placed in the FAQ. It took quite a bit on experimentation to get all this to work.
I hope this helps anyone with two or more external interfaces.