Metawerx Java Hosting Small Logo

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 "mysql.metawerx.net" on port 3306 (MySQL).
  • Without a firewall, the client would simply connect to mysql.metawerx.net:3306, as follows:
CLIENT--------((internet))---------mysql.metawerx.net:3306

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

CLIENT--------((internet))------|| FIREWALL ||-----mysql.metawerx.net:3306

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 (ssh.metawerx.net), which is able to connect directly to the database mysql.metawerx.net
  • The data between SSH and SSHD in encrypted
CLIENT--------((internet))-----|| FIREWALL ||-----mysql.metawerx.net:3306
       |                                                  |
       |                                           ssh.metawerx.net
       --SSH==((internet))==========================SSHD--|
               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 mysql.metawerx.net, the connection is now a local network connection. As a result, mysql.metawerx.net 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 ssh.metawerx.net:22
  • SSHD connects to MYSQL on mysql.metawerx.net:3306
    CLIENT                                                             MYSQL
localhost:anyport                                             mysql.metawerx.net:3306
       |                                                                 |
       |                                                                 |
localhost:3307                                                ssh.metawerx.net:anyport
       |--SSH================((internet))==========================SSHD--|
your_ip_address:anyport                                        ssh.metawerx.net:22

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 ssh.metawerx.net (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 ssh.metawerx.net, port 22 (the default)
  • Your username for ssh.metawerx.net is "ssh_cassie"
  • Your password is "cassiepass"
  • If using Windows, you have installed PLINK as c:\installers\putty\plink.exe

Windows:

c:\installers\putty\plink -C -v -l ssh_cassie -pw cassiepass -L localhost:3307:mysql.metawerx.net:3306 ssh.metawerx.net
                                                                -------------- ----------------------- ----------------
                                                                CLIENT SIDE    SERVER SIDE             GATEWAY (SSHD)

Linux:

ssh -Cv -L localhost:3307:mysql.metawerx.net:3306 cassie@ssh.metawerx.net
           -------------- -----------------------        ----------------
           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 (ssh.metawerx.net:22)
  • SSHD will connect to the SERVER SIDE (mysql.metawerx.net:3306)
  • 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
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
E
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.

Windows:

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

Active Connections

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

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.

Linux:

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

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

If you cannot see 127.0.0.1:3307 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 127.0.0.1:3307 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

navigation
metawerx specific
search
Share
tools
help

referring pages

Share