Iptables DNAT routing: refer to destination host with many IP addresses

iptableslinux-networkingnat;routing

I want all TCP and UDP packets destined for the host on port 3389 to be routed to a different address on the network. The host is the computer that hosts these iptables.

Starting with this, doesn't look so bad, although, it would be nice to combine TCP and UDP into one rule:

*nat
-A PREROUTING -i ens1 -d 10.58.0.1 -p tcp -m tcp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i ens1 -d 10.58.0.1 -p udp -m udp --dport 3389 -j DNAT --to-destination 172.20.0.201
COMMIT

But, there are about 5 interfaces that need to be allowed to do this and several others that do not. Ok, so, lets get to work:

*nat
-A PREROUTING -i ens1 -d 10.58.0.1 -p tcp -m tcp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i ens1 -d 10.58.0.1 -p udp -m udp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i tun0 -d 10.58.0.1 -p tcp -m tcp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i tun0 -d 10.58.0.1 -p udp -m udp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i tun1 -d 10.58.0.1 -p tcp -m tcp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i tun1 -d 10.58.0.1 -p udp -m udp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i tun2 -d 10.58.0.1 -p tcp -m tcp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i tun2 -d 10.58.0.1 -p udp -m udp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i tun3 -d 10.58.0.1 -p tcp -m tcp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -i tun3 -d 10.58.0.1 -p udp -m udp --dport 3389 -j DNAT --to-destination 172.20.0.201
COMMIT

Oh, but wait, the host has 6 different possible IP addresses, so now I have to repeat that block of rules 6 times with different destinations that all actually refer to the same host. That will take a total of 60 brittle entries. There must be a better way.

Question: How can I refer to the host universally? instead of saying:

-d <ip address>

… and repeating that line countless times, I would much rather say:

-d <catch-all for anything destined to this computer>

In my mind, it makes more sense to apply this DNAT rule to the INPUT chain but for reasons that are way beyond my comprehension, the INPUT chain seems to only accept SNAT rules. So, unless someone knows better, I am stuck in NAT PREROUTING.

Thanks and Regards

Best Answer

If you don't need to restrict the traffic by incoming interface name, then you can use

-A PREROUTING -d 10.58.0.1 -p tcp -m tcp --dport 3389 -j DNAT --to-destination 172.20.0.201
-A PREROUTING -d 10.58.0.1 -p udp -m udp --dport 3389 -j DNAT --to-destination 172.20.0.201

Then combining this with the ipset feature, you have only two lines. iptables multiple source IPs has information on the ipset feature.