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 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
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.
"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.
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.
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 ~/ sent 38 bytes received 36896584 bytes 1505984.57 bytes/sec |
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.
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 $ |
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.
Below are a couple of use cases where you can use GUI tools on your desktop to connect via these tunnels
OCI Console showing the connect string to the database in the example above
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
Connected
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
Consulting Cloud Solutions Architect - A-Team