The Secure Shell (ssh) is a universal tool when it comes to accessing machines remotely. Mostly known for opening a remote terminal environment there are much more possibilites hidden in its server functionality. One of them is tunneling. Tunnelings allows a remote host to function as a proxy server. This comes in handy when developing on a network infrastructure that has a DMZ.

A gateway server is used to route all incoming traffic. Servers inside the DMZ are effectively unreachable from the outside which is a valid security feature but can be a problem for temporary work. For instance, given a gateway server which runs a web application and another instance inside the DMZ running a PostgreSQL database.

+----------DMZ-----------+
|                        |
|  database.example.com  |
|                        |
+----------DMZ-----------+

         Gateway
       example.com
            |
      Local Machine

From a local machine you cannot connect remotely to the database. The DMZ is bypassed by using SSH tunneling. From a local machine with access rights to the gateway server a proxy is set up as follows:

$ ssh -L8888:database.example.com:5432 example.com

This connects to the gateway machine and creates a tunneling to the database instance. All traffic which reaches now port 8888 is forwarded to the database instance on port 5432. This allows us to connect to the database instance from our local machine:

$ psql -h example.com

psql (9.4.4)
Type "help" for help.

postgres=# SELECT * FROM users;

So far, so good. This becomes more tricky when another host from a different network is involved. I was working on a project in which data had to be collected from a remote instance to a web service sitting inside a DMZ as well:

+-----------DMZ------------+
|                          |
|  webservice.example.com  |
|                          |
+-----------DMZ------------+

          Gateway
        example.com
             |
       Local Machine
             |
        Data Store
       81.175.76.143

The web service depicted here cannot access the data store on 81.175.76.143. Our local machine is able to access the web service over normal SSH tunneling. Our web service is still unable to access the remote data store. With reverse tunneling we can use our local machine to route the packets to the data store:

$ ssh -L8888:webservice.example.com:20 example.com
$ ssh -R 9999:81.175.76.143:80 localhost -p 8888

All packets which arive on our local machine on port 9999 are now forwarded to the remote data store on 81.175.76.143 through port 80 by establishing a reverse tunnel connection on localhost using the SSH port 8888 which makes effective use of the first tunnel set up.