Linux IPTables Destination NAT with Asymmetrical Routing

iptableslinuxnat;networkingrouting

What is the proper way to handle DNAT when traffic leaves a different interface than it arrived on? When this happens it seems the reply doesn't have the source address replaced automatically as it would if it were going out the same interface it arrived on.

Edit — SNAT not working out for me:

Chain PREROUTING (policy ACCEPT 386 packets, 23372 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DNAT       all  --  *      *       0.0.0.0/0            12.12.12.5         to:10.7.0.5 

Chain POSTROUTING (policy ACCEPT 288 packets, 18672 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 SNAT       all  --  *      eth0    10.7.0.5             0.0.0.0/0           to:12.12.12.5 
    0     0 SNAT       all  --  *      eth3    10.7.0.5             0.0.0.0/0           to:12.12.12.5 
    8   550 MASQUERADE  all  --  *      eth0    172.16.14.0/30       0.0.0.0/0           
    0     0 MASQUERADE  all  --  *      eth0    10.7.0.0/24          0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 23 packets, 1572 bytes)
 pkts bytes target     prot opt in     out     source               destination

So in the above both routers have the same tables and same interface layout. eth0 on both routers are Internet connections and eth1 on each router connects to the same LAN (10.7.0/24). eth3 connects the two routers to each other.

What is happening is am pinging the 12.12.12.5 address from a location on the Internet. The replies go in Router B via eth0 and out eth1 with the destination nat working fine. The replies are entering eth1 on Router A and exiting the Internet via eth0 on router A. However, the source address is not being overwritten and the replies make it back to the device sending the pings with 10.7.0.5 address*.

*Yes, they actually make it across 20 hops with a private source IP and don't get squashed anywhere — kind of amazing).

Even More Edit:
Okay, apparently SNAT (at least it seems from the iptables manual) only matches if it is stateful. So I need stateless nat. This can be done with iproute2, but according to http://linux-ip.net/html/nat-dnat.html#ex-nat-dnat-full it can also be simulated by using –to-destination with SNAT in iptables. However, my ubuntu 10.04 just says unknown option --to-destination

Best Answer

To my knowledge, the address rewriting behaviour you're describing will happen so long as the outbound response packet is routed by the same router that routed / DNAT'ed the incoming request. If any other of the N+1 routers in the highly-available router pool are handling the outbound response packet, though, they're not going to "see" that connection in the Netfilter state database.

It sounds like you want a highly available Netfilter router that shares NAT state machine information. The ct_sync tool mentioned in that paper has been mostly abandoned, but the conntrackd tool from conntrack-tools has been developed to do some of the same things as ct_sync.

If you're planning on doing stateful packet filtering (or NAT, which is really just a superset of stateful packet filtering) then you're going to need a method to distribute the state database (or, alternatively, go with stateless filtering in the network and do stateful filtering on each host).