Your proxy server is thus doing a double NAT, masquerading (by hiding the other real peer) both ways.
It has to be configured as a router on its (single) interface or nothing will be forwarded. Let's say the interface name is eth0, and its IP is 10.1.2.50:
echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding
Now because of the double NAT, the transformations in PREROUTING and/or POSTROUTING prevent matching the flow just using again the same filter. So in PREROUTING a CONNMARK is used to mark the flow which can then be reused immediately in PREROUTING (and avoiding duplicating the specific test for easier management) and later in POSTROUTING. Note -p udp is still needed because we ask SNAT and/or DNAT to alter UDP ports. After that conntrack will handle all future exchange, as long as it doesn't time out (usually 30s for first reply, then 3mn)
iptables -t nat -A PREROUTING -s 10.1.2.10 -p udp --dport 5005 -j CONNMARK --set-mark 0x1 iptables -t nat -A PREROUTING -p udp -m connmark --mark 0x1 -j DNAT --to-destination 10.1.2.20:5010 iptables -t nat -A POSTROUTING -m connmark --mark 0x1 -j SNAT --to-source 10.1.2.50
If it's really a requirement that you also alter the source port, instead of having conntrack do it only when needed, change the 3rd rule into:
iptables -t nat -A POSTROUTING -p udp -m connmark --mark 0x1 -j SNAT --random-fully --to-source 10.1.2.50:32768-60999
(usual range taken from /proc/sys/net/ipv4/ip_local_port_range, and --random-fully is needed else nothing is done because the original port is already in range).
You could also change SNAT to MASQUERADE (and not have to state server IP) but only --random is available.
UPDATE: while the above rules work as intended, usually the connmark match and the CONNMARK target are intended for interaction with mark and MARK for a more complex usage as described in this blog. They are not needed for the simple usage here. Simply replace them all with resp. mark and MARK. Here netfilter's connection tracking already takes care of the flow once the first packet is handled (creating a conntrack entry in NEW state) without having to ask it to mark it in the conntrack entry. A mark is just put in the (first) packet (the nat table sees only packets in NEW state):
iptables -t nat -A PREROUTING -s 10.1.2.10 -p udp --dport 5005 -j MARK --set-mark 0x1 iptables -t nat -A PREROUTING -p udp -m mark --mark 0x1 -j DNAT --to-destination 10.1.2.20:5010 iptables -t nat -A POSTROUTING -m mark --mark 0x1 -j SNAT --to-source 10.1.2.50
Example captures, including errors (service not running etc.):
00:28:36.476453 IP 10.1.2.10.56955 > 10.1.2.50.5005: UDP, length 5 00:28:36.476487 IP 10.1.2.50.35172 > 10.1.2.20.5010: UDP, length 5 00:28:36.476516 IP 10.1.2.20 > 10.1.2.50: ICMP 10.1.2.20 udp port 5010 unreachable, length 41 00:28:36.476522 IP 10.1.2.50 > 10.1.2.10: ICMP 10.1.2.50 udp port 5005 unreachable, length 41 00:32:28.597050 IP 10.1.2.10.35443 > 10.1.2.50.5005: UDP, length 5 00:32:28.597084 IP 10.1.2.50.36842 > 10.1.2.20.5010: UDP, length 5 00:32:32.503709 IP 10.1.2.20.5010 > 10.1.2.50.36842: UDP, length 7 00:32:32.503745 IP 10.1.2.50.5005 > 10.1.2.10.35443: UDP, length 7 00:32:41.704371 IP 10.1.2.20.5010 > 10.1.2.50.36842: UDP, length 4 00:32:41.704404 IP 10.1.2.50.5005 > 10.1.2.10.35443: UDP, length 4 00:32:41.704427 IP 10.1.2.10 > 10.1.2.50: ICMP 10.1.2.10 udp port 35443 unreachable, length 40 00:32:41.704433 IP 10.1.2.50 > 10.1.2.20: ICMP 10.1.2.50 udp port 36842 unreachable, length 40
Please note that, you can replace all of this with this simple socat line (and you don't get any 30s/3mn timeout but you lose ICMP handling):
socat UDP4-LISTEN:5005,range=10.1.2.10/32,fork UDP4:10.1.2.20:5010