Skip to main content

notes and writeups

Making your local workstation a proxy between two remotes

Short background: recently I had to access an Oracle database and make a dump of it. The database was on a remote server that was accessible only via a VPN I had access to from my laptop. I didn’t have Oracle tools (like expdp or impdp) installed locally though. Instalation of those things on my local Ubuntu could be troublesome and I couldn’t find a suitable Docker image to use of out the box. I could use VM with CentOS and install all that Oracle related tools, but I had access to a remote server with those packages already installed.

I decided to use a reverse proxy functionality of SSH tool1. In short, this allows to create a tunnel between you and a remote using SSH protocol, and that tunnel can transport your regular network traffic (whether it is HTTP or a DB connection or another SSH session or…). It is helpful when all you have is an SSH access to a firewalled server, but you need to access another kind of service running on this server from outside. It is also helpful when you’d like to access a service on your localhost from a remote server (this is the case I use here). Specifically, from remote server I had to access a DB which was behind a VPN, but that VPN could be run only from my local workstation.

The command goes like this:

ssh -R port_on_remote:destination_host:destination_port your_ssh_params_to_remote

Where -R means to set up an endpoint on the Remote side. You can use -L instead if you need a local side.

My actual command was:

ssh -R 1234:10.10.10.15:1521 user@example.com

And a graphical explanation: SSH tunnel

After using this command you’d have a normal shell on the remote server opened (regular SSH session), but on port 1234 of that server, there is a tunnel listening. Connecting to it would in fact result in connecting to host 10.10.10.15:1521, which is hidden behind a VPN. All that traffic routes through your local machine using SSH protocol. Of course this tunnel is accessible for every user or service on the remote server.

Putting it in the background

Now above will create a regular, foreground SSH session. In case you don’t wan’t to have it opened for no reason, you might want to put it in the background with usage of additional parameters -f and -N as below:

ssh -f -N -R 1234:10.10.10.15:1521 user@example.com

-f is a parameter to put ssh session in the background2, but it requires a command to run on the remote server. Or a -N flag instead, described as “Do not execute a remote command.”. Opening a session this way leaves it open forever which might be not what you want. One way to finish it is to grep through ps and lsof outputs to find a correct PID to kill. Another, more elegant way is to create a UNIX control socket file to control the connection. Using additional flags -M (“master” mode) and -S /path/to/socket/file creates this file locally:

ssh -f -N -M -S /tmp/mysock.sock -R 1234:10.10.10.15:1521 user@example.com

Now the sessions starts in the background. To exit it, just pass exit command:

ssh -S /tmp/mysock.sock -O exit .

This sends “exit” signal to the connection handled by this socket file. Note the dot at the end - ssh command requires a “host” parameter in every case. As this time it is not needed (we operate only using socket file), this parameter can be whatever. You can put a dot or “asdf” in there. Executing the command returns:

Exit request sent.

and the tunnel is not available anymore.


  1. https://linux.die.net/man/1/ssh ↩︎

  2. https://unix.stackexchange.com/questions/83806/how-to-kill-ssh-session-that-was-started-with-the-f-option-run-in-background ↩︎