Transparently forward local port to remote server

I have StatsD daemon running on a remote server (x.x.x.x) at 8125. I would like to forward 127.0.0.1:8125 to x.x.x.x:8125.

I have already tried running the following on localhost

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p udp --dport 8125 -j DNAT --to x.x.x.x:8125
iptables -t nat -A OUTPUT -p udp --dport 8125 -j DNAT --to-destination x.x.x.x:8125
iptables -t nat -A POSTROUTING -d x.x.x.x -j MASQUERADE

But it is not forwarding correctly.

echo "test.test.test:1|c" | nc -w 1 -u localhost 8125

Fails with error nc: Write error: Connection refused

echo "test.test.test:1|c" | nc -w 1 -u 127.0.0.1 8125

Fails without any error

echo "test.test.test:1|c" | nc -w 1 -u x.x.x.x 8125

Works correctly

Also, will such a port forwarding cause any security issues?


Solution 1:

That's not possible.

Packets generated by local processes are not involved in the forwarding plan.

As a consequence you won't be able to use PREROUTING and FORWARD chains in the tables locally generated packets will go through, but only OUTPUT (in raw/mangle/nat/filter tables) and POSTROUTING (in mangle/nat tables) chains while the routing decision is already made and you can't change it.

In fact with your current iptables setup your rules will do the following considering your use case :

  • First rule : unreached.
  • Second rule : DNAT locally generated packets to x.x.x.x on the loopback interface.
  • Third rule : Masquerade packets going trough your loopback interface with the IP address of your loopback interface.

So the result is : local packets will try to reach x.x.x.x:8125 on your loopback interface.

This netfilter diagram can help you understand the location of locally generated packets in the global flow.