Notes on port-forwarding (tunneling)

Russell Bateman
June 2014
last update:

There are three types of tunnels or port-forwarding.

  1. Local port-forwarding in which connections from the ssh client are forwarded via the ssh server, then to a destination server.
  2. Remote port-forwarding in which conections from the ssh server are forwarded via the ssh client, then to a destination server.
  3. Dynamic port-forwarding in which connections from various programs are forwarded via the ssh client, then via the ssh server, and finally to several destination servers.
The first is the most common.

Local Port Forwarding

Lets you connect from your local computer to another server. To use local port forwarding, you need to know your destination server, and two port numbers. You should already know your destination server, and for basic uses of port forwarding, you can usually use the port numbers in Wikipedia's list of TCP and UDP port numbers, like 22 and 443 for ssh, 80 for HTTP, etc.

In the command below, option -L is for "local."

For example, say you wanted to connect from your host (computer) to http://www.ubuntuforums.org using an ssh tunnel. You would use source port number 8888 (an arbitrarily chosen alternate HTTP port for this example), the destination port 80 (the usual HTTP port because that's what ubuntuforums will be listening on), and the destination server itself www.ubuntuforums.org:

ssh -L 8888:www.ubuntuforums.org:80 host

Where host should be replaced by the name of your host (computer). You could use localhost for host, or 127.0.0.1 or your computer's hostname (if DNS is working). The -L option specifies local port forwarding. Visually, I think of this part of the command as "the tunnel" with ports (openings) on either end with the server in the middle.

For the duration of the ssh session, pointing your browser at http://localhost:8888/ would send you to http://www.ubuntuforums.org/.

In other words, with the tunnel set up, just think of there being a wormhole in the wall of your home and if you step through it, you'll magically end up at that server you indicated and able to go through its right port even though the label (port number) over the entrance to the wormhole in your house has a different port number over it.

Why would you do this?

Because, for example, at work they've locked you down behind a firewall and the only ports you can get out on are not the ones you need on the remote host. In this case, pretend they've locked down port 80, but you desperately need to use your browser to get to ubuntuforums.org and it's listening on port 80. But, in their infinite wisdom, IS&T have left you able to get out over port 8888. So you create a tunnel from your port 8888 to ubuntuforum's port 80.

(This example is a little bogus because typically port 80 is the only port left open to you in your firewall. But the illustration was easier to illustrate.)

More...

I haven't really finished this from here on...

In the above example, we used port 8888 for the source port. Port numbers less than 1024 or greater than 49151 are reserved for the system, and some programs will only work with specific source ports, but otherwise you can use any source port number. For example, you could do:

ssh -L 8888:www.ubuntuforums.org:80 -L 12345:ubuntu.com:80 host

...to forward two connections, one to www.ubuntuforums.org, the other to www.ubuntu.com. Pointing your browser at http://localhost:8888/ would download pages from www.ubuntuforums.org, and pointing your browser to http://localhost:12345/ would download pages from www.ubuntu.com.

The destination server can even be the same as the ssh server. For example, you could do:

ssh -L 5900:localhost:5900 host

This would forward connections to the shared desktop on your ssh server (if one had been set up). Connecting an ssh client to localhost port 5900 would show the desktop for that computer.

Remote Port Forwarding

In the command below, option -R is for "remote" and -N means "do not execute a remote command."

Let's say you want to do something on a remote server that's so secure that it's out of the question to punch a hole for a new port through its firewall. For example, let's assume you're trying to remote-debug using IntelliJ IDEA or Eclipse and there's a debug port you have to specify. You can't specify the port on the remote host because that's not allowed. However, you need to use a port to do this work.

The solution is a tunnel. The debug port could be the same or different at either end of the tunnel, but you've only got port 22 to carry the traffic on. Set it up this way:

ssh -f -L 8889:10.10.10.79:8889 [email protected] -N

This has you telling IntelliJ (or Eclipse) that your debug port is 8889. Similarly, on the remote host, it's 8889. But, it's the ssh session (port 22) that's carrying the traffic between localhost and the secure 10.10.10.79.

You could also have told IntelliJ (or Eclipse) that the port was 7979, but still had it be 8889 on the remote host:

ssh -f -L 7979:10.10.10.79:8889 [email protected] -N

See also http://java.dzone.com/articles/how-use-ssh-tunneling-get-your