If you have read the previous article of this series, you should be able to create forward and reverse tunnels with ease. In addition to the previously shown examples I will address some more advanced options for SSH tunnels in general.
SSH Login shell
Remember the following example:
ssh -L 5000:localhost:3306 email@example.com
Once you have executed the above command, a tunnel is established. However, you will also be logged in into the remote server with a SSH session. If you simply want to do some port forwarding you will not need or might not even want a remote login session. You can disable it via
-N, which is a very common option for SSH tunnels:
ssh -N -L 5000:localhost:3306 firstname.lastname@example.org
-N option is also very useful when you want to create SSH tunnels via cron
||After you connect just hang there (you won’t get a shell prompt)
SSH man: Do not execute a remote command.
Note: Only works with SSHv2
So if you are not going to execute remote commands and will not need a login shell, you also do not need to request a pseudo terminal in the first place.
ssh -T -N -L 5000:localhost:3306 email@example.com
||Disable pseudo-terminal allocation.
This makes it also safe for binary file transfer which might contain escape characters such as
SSH tunnel via cron
Imagine you want to have a SSH tunnel be established (or checked and if it doesn’t run re-opened) via cron every hour. For that to work, SSH must go into background. For that we use
ssh -f -L 5000:localhost:3306 firstname.lastname@example.org
||Requests ssh to go to background just before command execution.|
But hey, if SSH is in the background anyway, we do not need a login shell (
-N) and therefore also do not need a tty (
-T). So the full command ready for cron would be:
ssh -f -T -N -L 5000:localhost:3306 email@example.com
Note: Be aware that this example requires private/public key authentication as cron will not be able to enter passwords.
SSH tunnel on a non-standard port
What if the SSH server is listening on a non-standard port (not tcp22). You can always add a port option. Let’s imagine SSH itself is listening on port 1022:
ssh -T -N -L 5000:localhost:3306 firstname.lastname@example.org -p 1022
||Port to connect to on the remote host.|
SSH tunnel with a non standard private key
Let’s assume you have many different private keys for different servers. If not explicitly specified, SSH will look for a file called
~/.ssh/id_rsa. In this case however, your file is called
~/.ssh/id_rsa-cytopia@everythingcli. So you will also pass this information to the tunnel command.
ssh -T -N -L 5000:localhost:3306 email@example.com -i ~/.ssh/id_rsa-cytopia@everythingcli
SSH tunnel via SSH config
The most complex example from this tutorial is:
ssh -f -T -N -L 5000:localhost:3306 firstname.lastname@example.org -p 1022 -i ~/.ssh/id_rsa-cytopia@everythingcli
We all are lazy-ass and don’t want to type the whole thing every time we need a quick tunnel. This is where
~/.ssh/config comes into play.
Adding user and host
$ vim ~/.ssh/config Host cli HostName everythingcli.org User cytopia
With this, we have created an alias
cli for host
everythingcli.org with user
cytopia. Now our command can be written like this:
ssh -f -T -N -L 5000:localhost:3306 cli -p 1022 -i ~/.ssh/id_rsa-cytopia@everythingcli
Adding port and identity file
$ vim ~/.ssh/config Host cli HostName everythingcli.org User cytopia Port 1022 IdentityFile ~/.ssh/id_rsa-cytopia@everythingcli
Now the ssh command looks like this:
ssh -f -T -N -L 5000:localhost:3306 cli
Adding tunnel config
In the above example we have a generic configuration for the host
everthingcli.org which will work for normal ssh connection as well as for establishing a tunnel. Let’s copy all of the above block under a new alias
cli-mysql-tunnel and add the tunnel specific configuration:
$ vim ~/.ssh/config Host cli-mysql-tunnel HostName everythingcli.org User cytopia Port 1022 IdentityFile ~/.ssh/id_rsa-cytopia@everythingcli LocalForward 5000 localhost:3306
Now we can create the tunnel in a much shorter way:
ssh -f -T -N cli-mysql-tunnel