Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

The title pretty much sums it up. I would like to send UDP traffic through a SSH tunnel. Specifically, I need to be able to send UDP packets through the tunnel and have the server be able to send them back to me on the other side. I know how to do it for TCP connections. Is this it possible with UDP?

share|improve this question

4 Answers 4

up vote 20 down vote accepted

This small guide tells you how to send UDP traffic via SSH using tools that come standard (ssh,nc,mkfifo) with most UNIX-like operating systems.

Performing UDP tunneling through an SSH connection

Step by step Open a TCP forward port with your SSH connection

On your local machine (local), connect to the distant machine (server) by SSH, with the additional -L option so that SSH with TCP port-forward:

local# ssh -L 6667:localhost:6667 server.foo.com

This will allow TCP connections on the port number 6667 of your local machine to be forwarded to the port number 6667 on server.foo.com through the secure channel. Setup the TCP to UDP forward on the server

On the server, we open a listener on the TCP port 6667 which will forward data to UDP port 53 of a specified IP. If you want to do DNS forwarding like me, you can take the first nameserver's IP you will find in /etc/resolv.conf. But first, we need to create a fifo. The fifo is necessary to have two-way communications between the two channels. A simple shell pipe would only communicate left process' standard output to right process' standard input.

server# mkfifo /tmp/fifo
server# nc -l -p 6667 < /tmp/fifo | nc -u 192.168.1.1 53 > /tmp/fifo

This will allow TCP traffic on server's port 6667 to be forwarded to UDP traffic on 192.168.1.1's port 53, and responses to come back. Setup the UDP to TCP forward on your machine

Now, we need to do the opposite of what was done upper on the local machine. You need priviledged access to bind the UDP port 53.

local# mkfifo /tmp/fifo
local# sudo nc -l -u -p 53 < /tmp/fifo | nc localhost 6667 > /tmp/fifo

This will allow UDP traffic on local machine's port 53 to be forwarded to TCP traffic on local machine's port 6667. Enjoy your local DNS server :)

As you've probably guessed it now, when a DNS query will be performed on the local machine, e.g. on local UDP port 53, it will be forwarded to local TCP port 6667, then to server's TCP port 6667, then to server's DNS server, UDP port 53 of 192.168.1.1. To enjoy DNS services on your local machine, put the following line as first nameserver in your /etc/resolv.conf:

nameserver 127.0.0.1
share|improve this answer
12  
This solution is not safe. TCP streams are not guaranteed to preserve message boundaries, so a single UDP datagram may be split in parts, breaking any protocol. –  Juho Östman Aug 8 '11 at 15:50
2  
It could also be nice to use port 1153 instead of 6667 (from man SSH example), which is used by IRC. –  phil pirozhkov May 30 '12 at 14:04
    
@JuhoÖstman Thanks for pointing out this pitfall. Being aware of the problem... have you run accros a solution? would small enough messages be a way to make it likely to work? –  humanityANDpeace Mar 29 '13 at 7:42
1  
The solution would be to prepend a length to each packet before they are sent through the TCP stream, and reconstruct the original packets from that. It would easy to write a C script to do that, but I am not sure if a readily-available solution exists. In practice, the TCP usually seems to preserve message boundaries in this case, but strange failures can occur at any time. –  Juho Östman Apr 23 '13 at 9:33

SSH (at least OpenSSH) has support for simple VPNs. Using the -w or Tunnel option in the ssh client, you can create a tun device at both ends, which can be used to forward any kind of IP traffic. (See also Tunnel in the manual page of ssh_config(5).) Note that this requires OpenSSH (and probably root privileges) at both ends.

share|improve this answer
    
This requires root privileges on remote machine even for UDP tunneling of non-priviledged ports and PermitRootLogin set to not 'no'. Too bad. –  phil pirozhkov May 30 '12 at 14:03
    
@grawity Thank you for pointing out this option, which even when as pointed out by philpirozhkov the required root login. I wonder if there can be a way to trick it into not needing the root? –  humanityANDpeace Mar 29 '13 at 6:57
2  
@humanityANDpeace: You can precreate the tun/tap devices and make them owned by a specific user, using ip tuntap add. –  grawity Nov 6 '13 at 18:08

This example (I think John's answer points the the same thing at a different place), describes how to access another machine's UDP/DNS services over an TCP/SSH connection.

We will forward local UDP/53 traffic to TCP, then TCP traffic with the port-forwarding mechanism of SSH to the other machine, then TCP to UDP/53 on the other end.
Typically, you can do it with openvpn.
But here, we'll do it with simpler tools, only openssh and netcat.

At the end of that page, is another comment with a reference to 'socat',
The same UDP/DNS access is made with,

Server side: socat tcp4-listen:5353,reuseaddr,fork UDP:nameserver:53
Client side: socat udp4-listen:53,reuseaddr,fork tcp:localhost:5353

Refer socat examples for more.

share|improve this answer
1  
This one seems much more useful for me than the accepted answer. I needed a unidirectional redirection of video stream (TS/UDP)... ssh orig_strm_src socat udp4-listen:4003,reuseaddr,fork STDOUT| socat STDIN udp-sendto:localhost:4003 –  nhed Jul 24 '12 at 23:11
    
FWIW, I've written a more detailed guide on my home page describing how to set up socat over SSH for UDP forwarding. It uses SNMP as an example. –  Peter V. Mørch Oct 8 '13 at 5:44

A VPN is a better solution if you have access to an UDP port.

If you only have access to the TCP SSH port, then an SSH tunnel is as good as a VPN, at least for ping and packet backtracking.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.