Crates.io | udp-over-tcp |
lib.rs | udp-over-tcp |
version | 0.1.2 |
source | src |
created_at | 2024-07-24 15:29:54.672163 |
updated_at | 2024-07-24 19:33:48.045927 |
description | Command-line tool for tunneling UDP datagrams over TCP. |
homepage | |
repository | https://github.com/jonhoo/udp-over-tcp |
max_upload_size | |
id | 1314095 |
size | 89,151 |
A command-line tool for tunneling UDP datagrams over TCP.
It is particularly useful for tunneling UDP over SSH
The tool was designed primarily for the use-case where you have two applications that need to talk to each other over UDP without an obvious client-server relationship. That is, either application may initiate a packet, and must be configured with the address of the other at start-up (i.e., ports cannot be random).
You run udp-over-tcp
on both applications' hosts. Each instance acts
as a kind of local replica on the application running on the other. If
the application on one host listens on UDP port P, then udp-over-tcp
will listen on UDP port P on the other host, and ensure that traffic
to the replica P goes to the real application's port P. Crucially,
udp-over-tcp
will do this for both applications' ports at the same
time and bond the ports. It will effectively "pretend" that each
application is running locally to the other.
Concretely, if the application on one host sends a datagram from its port P to (local replica) port Q, the datagram will arrive at the real (remote) application's port Q with a source port of P. This means that an application always sees the same single address (localhost) and port (the other application's port), and that same address-host pair can also be used in the peer configuration for the application.
Hopefully the following diagram can aid in understanding the setup
udp-over-tcp
configures:
The program comes pre-compiled for a number of platforms (thanks cargo-dist!), and should be executable out of the box with no dependencies.
Alternatively, you can install it through Cargo with
$ cargo install udp-over-tcp
You have a UDP application running on host X on port A. You want it to talk to a UDP application running on host Y on port B. And you also want to allow the application on Y to talk to A on X. Great, do as follows:
On either host (here X), first create a TCP tunnel to the other host:
ssh -L 7878:127.0.0.1:7878 $Y
Next, run udp-over-tcp on both hosts, one with --tcp-listen
and one with --tcp-connect
.
The --tcp-listen
should be used on the host that the forwarding allows connecting to (here Y).
You can run them in either order, but best practice is to listen first:
Y $ udp-over-tcp --tcp-listen 7878 --udp-bind $A --udp-sendto $B
X $ udp-over-tcp --tcp-connect 7878 --udp-bind $B --udp-sendto $A
On Y, this will listen on UDP port $A, forward those over TCP to X, and then deliver them to UDP port $A there. On X, this will listen on UDP port $B, forward those over TCP to Y, and then deliver them to UDP port $B there.
Now configure the application on X to send to 127.0.0.1:$B and configure the application on Y to send to 127.0.0.1:$A. In other words, same port, local IP address.
Each argument takes a port number (as above) or addr:port to specify the address. (address defaults to 0.0.0.0 for listen/bind and 127.0.0.1 for connect/sendto)
There exist other tools that can help with this problem, though they have different properties than this tool.
Solutions relying on nc
or socat
do not preserve UDP datagram
boundaries, meaning two UDP sendmsg
can cause only a single (combined)
message to arrive through recvfrom
. Many UDP applications are not
resilient to this as they rely on UDP to provide message framing.
mullvad's udp-over-tcp only provides unidrectional forwarding. One can run additional instances of the tool to forward in the other direction, though doing so means the source port of incoming datagrams will not match the destination port of outgoing datagrams. However, this is likely fine for client-server style applications where the client's port isn't important.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.