SSH Port Forwarding for TCP and UDP Packets

SSH port forwarding creates a secure tunnel between the client and server computers. As the connection is encrypted, SSH tunneling is useful for transmitting unencrypted (or non secure) protocols such as POP3, VNC, RDT, etc. SSH port forwarding also allows you to connect computers from two different networks that are not able to communicate with each other directly. In this article, we are going to see how we can use SSH tunnels to forward TCP and UDP packets.

Network

This is going to be our network scenario for this article.

ssh port forwarding network

The client computer will establish a SSH session to server server01 and access services (TCP port 80 and UDP port 53) on server server02.

We are also only going to talk about local port forwarding and not remote port forwarding. Local port forwarding lets you connect from your local computer to another server via the SSH server. Remote port forwarding is to connect the other way round – from a server to your computer or to another server via the SSH client.

Tools Required for SSH Port Forwarding

For the CLI based SSH client, we will be using the standard ssh program – an OpenSSH based SSH client. This is found in all Linux distributions. If you are looking for a CLI based OpenSSH client on Windows, install a copy of Cygwin.

PuTTY will be used as the GUI based SSH client. This is optional and not really required.

SSH only allows TCP port forwarding. To relay UDP packets, we will be using socat – a multipurpose relay (SOcket CAT). Under UNIX or Linux, install socat by using the default package installation utility. On Ubuntu, you would need to do something like this:

$ sudo apt-get install socat

Perform a Google search if you are looking for a socat binary for Windows.

SSH Port Forwarding for TCP

SSH supports forwarding of TCP ports by default, so this is going to be the easiest. We will tunnel port 80 (HTTP) on server02 to port 8000 on the client.

On PuTTY, create a new session towards the server.

putty session

Next, navigate to Connection->SSH->Tunnels, enter “8000” on the Source Port field and “10.0.0.20:80” on the Destination field. Click on the ‘Add’ button and you will see “L8000 10.0.0.20:80″ appear in the ‘Forwarded ports’ list.

putty ssh tunnel

Now save the PuTTY SSH session by navigating to the ‘Session’ category. Once the session is saved, login to the ssh server (server01) by clicking the ‘Open’ button at the bottom. Login to the server by entering the login credentials when prompted. Port forwarding is now enabled.

To perform the same action from the CLI, execute the ssh command in the following manner on the client computer:

client$ ssh -L 8000:10.0.0.20:80 user@server01

The above command tells the ssh program to listen on TCP port 8000 on the client computer and forward it to TCP port 80 on server02 (10.0.0.20).

The SSH tunnel is now established. To test the connection, use a HTTP client (curl command or your browser) and point it to http://127.0.0.1:8000. You should be able to get a response from the HTTP server running on server02.

client$ curl http://127.0.0.1:8000

This type of port forwarding will not work for FTP sessions. To tunnel FTP sessions, read this article: SSH Port Forwarding for FTP

SSH Port Forwarding for UDP

UDP port forwarding is a bit more complicated. We will need to convert the packets from UDP to TCP on the SSH client side, tunnel it over the SSH connection and convert it back from TCP to UDP on the SSH server side. We will tunnel UDP port 53 on server02 to UDP port 53000 on the client. We will use TCP port 8000 for the SSH tunnel.

The packet flow is shown in the diagram below.

ssh port forwarding udp

DNS requests sent to UDP port 53000 are relayed to TCP port 8000 on the client computer. The packet is then tunneled via the SSH connection. On server01, at the end of the SSH tunnel, the TCP packet on port 8000 is converted back to UDP and gets forwarded to server02 on UDP port 53. The reply flows back in a similar fashion.

Setup the SSH tunnel on TCP port 8000 by making a SSH connection from the client computer to server01.

client$ ssh -L 8000:127.0.0.1:8000 user@server01

The above command will instruct ssh program to listen on TCP port 8000 on the client computer and forward it to TCP port 8000 on server01 local interface (127.0.0.1).

Next, configure TCP-UDP relay on server01 using socat.

server01$ socat tcp4-listen:8000,reuseaddr,fork udp:server02:53

The above command instructs socat to listen on TCP port 8000 and redirect it to UDP port 53 towards server02.

Next, we also need to configure a UDP-TCP relay on client computer using socat.

client$ socat -T15 udp4-recvfrom:53000,reuseaddr,fork tcp:localhost:8000

This time we are telling socat to listen on UDP port 53000 and redirect it to TCP port 8000 on the loopback interface. The SSH tunnel will deliver the packets on TCP port 8000 to the server (server01).

Once done, we can test the tunnel by performing a simple DNS query on the client computer. We will need to specify the nameserver IP address of 127.0.0.1 as well as the port number of 53000 to the DNS query tool.

client$ dig @127.0.0.1 -p 53000 google.com

ibrahim = { interested_in(unix, linux, android, open_source, reverse_engineering); coding(c, shell, perl, php, python, java, javascript, nodejs, angular, react); plays_on(xbox, ps4); linux_desktop_user(true); }