SSH Tunnel

What is an SSH Tunnel?

A secure tunnel between two machines using the SSH protocol.

An SSH tunnel exists between an SSH client such as PuTTY/PLINK (Windows) or ssh on Linux, and an SSH Server (sshd). It can be used to securely connect a client on one machine to a server that is behind a firewall, by "tunnelling" all communications through the SSH connection.

How does the tunnel work?

The best way to describe an SSH tunnel is with a diagram.

Consider the following, which shows a normal connection between two machines:

  • Application "CLIENT" wants to connect to a database server "" on port 3306 (MySQL).
  • Without a firewall, the client would simply connect to, as follows:

However, the server is behind a firewall for security purposes, so the client is unable to connect

CLIENT--------((internet))------|| FIREWALL ||

Using SSH, we can create a way around the firewall, called a tunnel, which allows authentication and encryption of data.

  • The SSH client (or PuTTY, or PLINK) runs on the client machine
  • The SSHD server runs on a connection-gateway server (, which is able to connect directly to the database
  • The data between SSH and SSHD in encrypted
CLIENT--------((internet))-----|| FIREWALL ||
       |                                                  |
               this part is the secure SSH tunnel

Two more ports and hosts are now involved in the connection, making it more complex than before. However, the tunnel allows us to authenticate and send all traffic through the SSHD gateway server. To, the connection is now a local network connection. As a result, is now happy to accept our connection.

The following diagram shows all the port numbers being used above. This will be important when learning how the tunnel commands work.

  • When making connections outward, a random port number is selected. It is only the "listening" ports (connections inward) that we are concerned with.
  • The CLIENT connects to SSH on port localhost:3307
  • SSH connects to SSHD on
  • SSHD connects to MYSQL on
    CLIENT                                                             MYSQL
       |                                                                 |
       |                                                                 |

As you can see, because of the connections, CLIENT thinks it is connected to a local database running on localhost:3307. Likewise, the MYSQL server thinks it is receiving a connection from (a local server, inside the firewall).

In this way, we are tricking the CLIENT and MYSQL by tunnelling all data securely between the two machines.

How to set up a tunnel

Now let's look at the command to establish the tunnel above. We will assume the following:

  • Your gateway server is, port 22 (the default)
  • Your username for is "ssh_cassie"
  • Your password is "cassiepass"
  • If using Windows, you have installed PLINK as c:\installers\putty\plink.exe


c:\installers\putty\plink -C -v -l ssh_cassie -pw cassiepass -L
                                                                -------------- ----------------------- ----------------
                                                                CLIENT SIDE    SERVER SIDE             GATEWAY (SSHD)


ssh -Cv -L
           -------------- -----------------------        ----------------
           CLIENT SIDE    SERVER SIDE                    GATEWAY (SSHD)

The important parts are underlined.

  • We are asking SSH to listen on the CLIENT SIDE (localhost:3307) on our local machine
  • After we connect to localhost:3307, SSH will tunnel to SSHD (
  • SSHD will connect to the SERVER SIDE (
  • Our data will be passed to SSH, which will pass it through the tunnel to SSHD on the gateway, and SSHD will pass it on to the server

Checking the tunnel is active

If the tunnel is active and everything is working as expected, you should be able to connect to localhost:3307 with your client, and start interacting with the database. You can also try connecting with telnet.

telnet localhost 3307

If a blank screen appears, or something like the following, your tunnel is working well.

root@kirara:~# telnet localhost 3307
Connected to
Escape character is '^]'.
4.1.21-community-nt-log!m~Ui4cwMYV(`Connection closed by foreign host.

However, if you receive an error such as the following, your tunnel is not healthy.

telnet: Unable to connect to remote host: Connection refused

Let's look at some commands you can use to check that your SSH command is working the way you expected.

We can verify the CLIENT SIDE and GATEWAY parts of the command by checking if SSH is listening on the expected port. This is done by using netstat, which shows all listening ports and connections on your machine.


C:\Documents and Settings\Administrator>netstat -na

Active Connections

  Proto  Local Address          Foreign Address        State
  TCP              LISTENING
  TCP              LISTENING   <=== Yes, listening on
  TCP              LISTENING        ( is the same as "localhost")
  TCP              LISTENING
  TCP              LISTENING   We are also listening on a lot of other ports,
  UDP            *:*                                but that is not important for this tutorial,
  UDP            *:*                                so just look for, or whatever you
  UDP           *:*                                used in the CLIENT SIDE of the tunnel.
  UDP        *:*

C:\Documents and Settings\Administrator>

On linux we use netstat as well. We will also use grep to ignore all lines except those that contain the text "3307" - the port we are checking for.


root@kirara:~# netstat -pant | grep 3307
tcp    0    0*   LISTEN     16930/ssh   <=== Yes, listening on

# If no lines are shown, you have nothing listening on port 3307

If you cannot see in the netstat command, your SSH program is not listening correctly, so retry the PLINK or ssh command.

If you close the tunnel by closing PuTTY/PLINK/SSH, you should notice that the listening port on disappears.

If you have verified that SSH is listening, then you have a good connection to the GATEWAY (SSHD) and the CLIENT SIDE of the tunnel appears to be working. If the tunnel itself still isn't active, then there could be a problem in the SERVER SIDE of the command. This can be seen in the logs on the server.

The point of this guide was to give a description of the way the tunnel works, and how to construct tunnels of your own.

If you are having problems setting up a tunnel, please continue by reading SSH Tunnel Troubleshooting, which contains guides to error messages and more help.

See Also

metawerx specific

referring pages