Setting up UDP packets to two different destinations using iptables and PREROUTING

I am trying to send a UDP on a packet to two different external/remote IPs using iptables.

Currently I am running a command that looks like this:

iptables -t nat -A PREROUTING -i eth0 -p udp --dport 3070 -j DNAT --to-destination
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 3070 -j DNAT --to-destination

However, this does not work, because the UDP packet looks at the iptables’ rules, and goes to Putting the other rule first makes the UDP packet go to that second destination. I tried combining the actual to-destinations using their range functionality, but the packet does not go anywhere, as these ranges are not internal IPs:

iptables -t nat -A PREROUTING -i eth0 -p udp --dport 3070 -j DNAT --to-destination

### note: I also tried
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 3070 -j DNAT --to-destination

where the port is increased by one on the secondary server

I can confirm that both commands work separately, and that only one works when both are in the same rule hierarchy.

I have also tried to use TEE to make this work, pointing to one of the IPs as another gateway, but that doesn’t work either. Is there any way to do this in iptables, or am I missing the mark in creating a multi-destination general UDP forwarder?

The UDP packets should both be distributed at the same time/simultaneously and duplicated to each respective server. The use case at the moment is that the UDP packet is needed for a process on Server A as well as in Server B, but from the source side that is sending the packet, it can only point to one server. ie: Server C that sends udp packets -> Server D -> duplicate and send packet to Server B and Server A.

Thanks for any help or suggestions.

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Simple userland tools

First I would recommend using a dedicated tool running on server D that will listen for UDP packets, and will send a copy twice, one for A and one for B. This could be done for example with bash process substitution+tee+socat (example loosely adapted from with its handy reversed order, to have tee immediately running) , but I don’t know if some buffering might not happen in some cases (better create a dedicated application):

socat -U - udp4-recv:3070 | tee >(socat -u - udp4-datagram: | socat -u - udp4-datagram:

Using kernel (iptables … -j TEE)

Now that is said, for a “kernel-assisted” method, there’s iptables’s TEE target which can duplicate packets. Because the duplication has to bypass the normal routing handling, it requires to “evacuate” the duplicated packet to an other host directly reachable (the –gateway parameter). Without this, it appears there’s no good way to handle the copied packet with TEE.

Fair enough, we can just create that host using a network namespace. Then reinject right back the duplicated traffic on host D, through the routing stack and iptables which can now DNAT it differently (because it came from an other interface). Because of the assymetric routing and the duplicate flow some adjustements have to be done (loose rp_filter on the virtual interface, and a different conntrack (origin) zone to differentiate the flows, because conntrack knows only about IPs, not interfaces)

Here’s the configuration to use on Server D (some duplication could probably be avoided, but it would be less readable):

ip netns del dup 2>/dev/null || : # to remove previous instance, if needed
ip netns add dup

ip link add name dup1 type veth peer netns dup name eth0
ip link set dup1 up
ip -n dup link set eth0 up
ip address add dev dup1
ip -n dup address add dev eth0
ip -n dup route add default via
sysctl -q -w net.ipv4.conf.dup1.rp_filter=2
ip netns exec dup sysctl -q -w net.ipv4.conf.eth0.forwarding=1
iptables -t mangle -A PREROUTING -i eth0 -p udp --dport 3070 -j TEE --gateway
iptables -t raw -A PREROUTING -i dup1 -p udp --dport 3070 -j CT --zone-orig 1
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 3070 -j DNAT --to-destination
iptables -t nat -A PREROUTING -i dup1 -p udp --dport 3070 -j DNAT --to-destination

With this method even replies from A and B can both be sent back to C (which will think they both came from the very same initial destination), if this makes sense anyway. So if nothing is listening on A or B, an ICMP destination port unreachable will be sent to source C, which might choose to abort: additional firewalling to avoid this should probably be added somewhere.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply