Simplify your day with SSH config file entries and self closing tunnels

March 12, 2020 | 7 minute read
Mikael Fransson
Consulting Cloud Solutions Architect
Text Size 100%:

Introduction

I guess we're all familiar with ssh connection strings and I see them typed over and over on various web conferences when helping out customers or on internal demos. Since we very often connect to the same hosts over and over, at least during the length of a project. Iit would be nice if we could hide the complexity. I also struggle with syntax every time I need to setup a tunnel and forward ports on the command line. Over the years I have gathered a large collection of samples and blog posts. What has simplified my ways around SSH and tunnels is to put it all in the SSH Config File. I can comment on the setups, have templates to copy from and I need to type less on the command line. 

A common use case

A simple and common use case is to access a VM DB System (or any host in a private subnet). Since it's not recommended to put a database in a public subnet you need to access it via a bastion host. Either you have a dedicated bastion host or you can use any compute instance with a public IP that you have access to and that sits in the same VCN. We have a white paper describing the bastion host setup. This is a good starting point, https://docs.cloud.oracle.com/iaas/Content/Resources/Assets/whitepapers/bastion-hosts.pdf
In my use case, I want to use tools like SQL Developer to connect directly to the database via the bastion host or GUI apps like FileZilla to copy files, RDP clients for Windows hosts, VNC clients etc.. Then it's both convenient and secure to create an ssh tunnel and forward these remote ports to your local machine.

In this test setup, the VCN has two subnets, one public and one private. All security lists and route tables are default.

A Compute instance in the public subnet will be the bastion host via which we will connect to hosts and services in the private subnet.

The compute instance has two IP's:
Public: 129.146.177.249
Private: 10.40.1.2

The DB host in the private subnet has one IP:
Private: 10.40.2.2

 

SSH Config configuration details

Host, an alias for the entry
User, the expected and always present opc user
Hostname, the address to the host you want to connect to
Port, the ssh port
IdentityFile, the location of your private keyfile
UseKeychain, if your ssh key have a password you only need to enter it the first time and then it will be saved in the macos keychain or Gnome keyring
ProxyJump, describes the chain of hosts to connect via (jump through) to get to the remote host. Multiple hosts can be specified separated by a comma. ProxyJump is a simplification of the older ProxyCommand.
LocalForward, the directive on what port to forward to your local machine from the remote host.

# $HOME/.ssh/config
#
# Permissions: User R/W, NOT Writable by others
# chmod 700 $HOME/.ssh
# chmod 600 $HOME/.ssh/config
# First some generic settings that applies to all specific hosts below unless specified otherwise
Host *
    IdentityFile ~/.ssh/id_rsa
    ServerAliveInterval 240
    ServerAliveCountMax 2
    TCPKeepAlive yes
    UseKeychain yes

Host mydb
    User opc
    HostName 10.40.2.2
    Port 22
    ProxyJump opc@129.146.177.249
    # Jump through more hosts
    # ProxyJump user@host1,user@host2,user@host3
    # 1521 is the default SQL*Net port used for all database traffic
    LocalForward 1521 localhost:1521
    # 5901 is for VNC. On Windows you can see it
    # referenced as :0 which means 5900, :1 is 5901 etc.
    LocalForward 5901 localhost:5901
    # 22 is the default ssh port.
    # Here forwarded to 2242 on your local machine.
    # A little redundant here but just included as another example
    LocalForward 2242 localhost:22

The above works on macOS and Linux. Windows might have some small differences. A collegue just posted a blog around ssh tunneling and using Putty to configure this. I think most windows users are familiar with Putty. You can also install OpenSSH on Windows now.

Always use VNC via an ssh tunnel

"Four popular open-source VNC remote desktop applications have been found vulnerable to a total of 37 security vulnerabilities, many of which went unnoticed for the last 20 years and most severe could allow remote attackers to compromise a targeted system."

https://thehackernews.com/2019/11/vnc-remote-software-hacking.html

With the configuration above you can open a VNC session to the database host on 10.40.2.2 with something vnc://localhost:5901 (provided that there is a VNC server on that host of course). The VNC traffic is now encrypted. This doesn't solve the bugs found but it at least protects the traffic as VNC in itself is not a secure protocol.

Start an ssh session

With the above in the ssh config file simply connect with ssh mydb

$ ssh mydb
Last login: Mon Oct  7 11:11:04 2019 from 10.0.1.2
[opc@mydb ~]$

Since we defined ports to be forwarded to our local machine from the remote host we can confirm that they are available locally.

$ netstat -an |grep 1521
tcp4       0      0  127.0.0.1.1521         *.*                    LISTEN   
tcp6       0      0  ::1.1521                    *.*                    LISTEN   
$ netstat -an |grep 5901
tcp4       0      0  127.0.0.1.5901         *.*                    LISTEN   
tcp6       0      0  ::1.5901                    *.*                    LISTEN   
$ netstat -an |grep 2242
tcp4       0      0  127.0.0.1.2242         *.*                    LISTEN   
tcp6       0      0  ::1.2242                    *.*                    LISTEN   
$

When we exit the ssh session the tunnel and ports will go down unless something is connected to the ports.

Copy a file on the command line

In the example below scp is using the ssh/config entry to connect to the host mydb via the bastion host to copy the remote file (somelogfile.log).
The logfile is 40Mb and it copied to my local machine at 2.1MB/s.

$ scp mydb:~/somelogfile.log ~/
somelogfile.log                                              100%   40MB   2.1MB/s   00:19


The same operation using rsync

rsync -azv mydb:~/somelogfile.log ~/
receiving file list ... done
somelogfile.log

sent 38 bytes  received 36896584 bytes  1505984.57 bytes/sec
total size is 41923452  speedup is 1.14

rsync is of course the obvious choice when you have lots of files/folders to copy and it's a process that can be resumed and trusted to keep local and remote folders in sync.
Can typically be part of a cronjob.
 

Start a self-closing tunnel

You can start an ssh tunnel and send it to the background but then it's a little tricky to find it and close it when you don't need it anymore. Better if you could send it to the background and let it close itself when it's not used anymore. Found this little clever trick online somewhere.

ssh -f mydb sleep 10

-f Requests ssh to go to background just before command execution
sleep 10 will execute on the remote host and if nothing connected within the time allotted (10 seconds) the tunnels will close again. Increase the time as needed.

$ netstat -an |grep 1521
tcp4       0      0  127.0.0.1.1521         *.*                    LISTEN   
tcp6       0      0  ::1.1521                    *.*                    LISTEN   
$ netstat -an |grep 2242
tcp4       0      0  127.0.0.1.2242         *.*                    LISTEN   
tcp6       0      0  ::1.2242                    *.*                    LISTEN   
$

 

SOCKS proxy in SSH Config

A SOCKS proxy can come in handy to redirect all your traffic over the ssh tunnel.

The entry below in ssh/config will configure a SOCKS proxy to a Vbox/Vagrant VM that in turn can be connected to another network via a VPN

Host myproxy
    Hostname 127.0.0.1
    Port 2222
    User vagrant
    DynamicForward 1337


Now you can simply start the SOCKS proxy with:

ssh myproxy


Run the proxy in the background with:

ssh -f myproxy sleep 10

As above, if nothing connects within 10 seconds the SOCKS proxy tunnel closes itself.

With the tunnel running you can configure Firefox to use this SOCKS proxy and send all requests via the proxy. This will not affect the rest of the system.

If you don't want to send all traffic (URL's) through this SOCKS proxy you can use a Firefox Add-On like FoxyProxy that allows you to filter which URL's will go via the proxy.

Using the tunnels with some client tools

Below are a couple of use cases where you can use GUI tools on your desktop to connect via these tunnels

A database on OCI

OCI Console showing the connect string to the database in the example above

Connect with SQL Developer

Connection setup. Since the remote host has its SQL*Net port forwarded to my mac (also using 1521 as I don't have a database on my mac and the port is free). The host is localhost and the Service name has the Easy connect string from the OCI dialog above.

Connected via the ssh tunnel

Connect with FileZilla

Connected

sshuttle - a poor mans VPN

Recently stumbled over this little utility that allows you to configure a VPN connection to any host you have ssh access on. The remote machine doesn't need any specific software or root access, only Python 2.3 or higher is needed. On your local machine you need root or sudo access. Sshuttle is open source and command line only. Supports most linux platforms and macOS.

On macOS you would install it with Homebrew: brew install sshuttle

It also honors aliases defined in ~/.ssh/config so starting a VPN is as simple as:

sshuttle -r vm2 0.0.0.0/0 -v

Where vm2 is an alias in ~/.ssh/config

Obviously you can use the IP of the remote host but if the VPN end point (the remote host) doesn't have a public IP it's easy to configure ProxyJump statements as shown in this blog so the VPN tunnel can pass through any number of remote hosts.

All the details here: https://github.com/sshuttle/sshuttle

 

Mikael Fransson

Consulting Cloud Solutions Architect

Consulting Cloud Solutions Architect - A-Team


Previous Post

SSH tunnel to a private VM using a Bastion host in OCI

Andrei Stoian | 5 min read

Next Post


Trigger OIC Integration Using OAuth Client Credentials

Greg Mally | 1 min read