Think of it as poor man's single-port UDP DNAT/SNAT.


./udpfwd <dest_ip> <dest_port> <listen_port>

The relay listens for packets received on listen_port, changes their source IPs to the IP of the local host ("SNAT"), and forwards them to the destination (dest_ip:dest_port) from a randomly chosen local send_port. The selection of send_port is made on reception of the first packet from a given source_ip:source_port; once chosen, the source_ip:source_port:send_port triplet is unique, allowing for connection tracking. Therefore, when a packet is received on send_port, its destination is changed to source_ip:source_port ("DNAT"), and forwarded onwards.

Effectively, this is a userspace SNAT/DNAT.


[host_a:xxxx] <-------> |          a_out:| <-------> [                   ]
[host_b:yyyy] <-------> |:listen   b_out:| <-------> [ dest_ip:dest_port ]
[host_c:zzzz] <-------> |          c_out:| <-------> [                   ]

Getting the Sources

Download them from

Building and Installing

A simple

cd src && make

should do. Then copy the executable `udpfwd' to wherever you like (e.g., /usr/local/bin).


A connection log and status file will by default be created in subdirectory log of the directory from which you start udpfwd. If the the log file cannot be written for any reason, logging will be disabled.

You can change the log and status file destinations using the —log and —status command line options.

Where is this useful

Wherever you don't have control over kernel-level routing/forwarding. For example, when attempting to set up an OpenVPN tunnel on an OpenVZ VPS where the hosting company disallows access to IP forwarding (I'll let you figure out the details :-)).


Two other tools are included in the package, mainly to make the testing easier. They are:

./reflect <port_to_listen_on>
UDP packet reflector -- returns received packets to the
./send <dest_ip> <dest_port> <source_port> [seconds_between_packets=1]
Sends a stream of UDP packets to dest_ip:dest_port. UDP
packets are sent from source_port. When a packet is sent,
waits for 1 second for a reply. After receiving the reply
(or after 1 second expires), waits for
seconds_between_packets seconds and repeats.

You may use these to test the relay. E.g.

Host A:  ./relay   Host_B 5000 4999
Host B:  ./reflect 5000
Host C:  ./send    Host_A 4999 6000

In the example above, ./send (executed on Host_C) will send packets from port 6000 to Host_A's port 4999. ./relay will forward these to Host_C's port 5000. These will be reflected by ./reflect and passed back through the relay to ./send.

License and Warranty

Copyright © 2008 Mario Juric <>

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, Version 2, as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA