SSH Is Magic, But Tunnels Are Even Better

Once upon a time, I was doing on-site support for a hardware install at a hotel a few years ago. The remote tech’s remote desktop software didn’t want to play with my Linux laptop, so he couldn’t get into the switch he needed to configure, to make the install work. I asked if it had an SSH port he could use, were he were in the room with me. Of course it did, but that didn’t do him much good. I ran a reverse SSH tunnel out to my public server, and pointed it at the switch on the local side. I convinced him to SSH to my server on the given port, and he was magically connected to his switch. He was literally in awe of that trick, and demanded to know how it could be done. SSH is magical, but tunneling traffic over SSH is straight-up wizardry. [Shawn Powers] agrees, and decided to help the rest of us understand the process.

There are two basic ways to launch a tunnel, the first being a local tunnel, that listens on the local machine, and forwards it to the remote machine. On the other hand, a remote tunnel will listen on the remote machine, and deliver the traffic to the local machine. The real fun begins when you have multiple SSH sessions, and connect one tunnel to another, to route something just where you need it. For extra credit, check out the hidden SSH command line, by pressing Enter, then tilde and the C key, each one at a time. Also for extra credit, check out the rest of [Shawn]’s Linux content, to learn some extra Linux goodness.

17 thoughts on “SSH Is Magic, But Tunnels Are Even Better

  1. Also, more recently SSH implemented ProxyJump which is fantastic for when you need to SSH through a series of servers. Instead of copy your key through every server or setting up a new tunnel at every level, you can use ProxyJump to magically forward your authentication to each server.

      1. Suppose to reach “target” you need to ssh to “bastion”, “client”, then “target” each with separate keys. You could setup your ~/.ssh/config file like so:

        Host target
        User bob
        Port 7654
        IdentityFile ~/.ssh/target.key
        ProxyJump client

        Host client
        User bb
        Port 10022
        IdentityFile ~/.ssh/client.key
        ProxyJump bastion

        Host bastion
        Port 22
        User bastionuser
        IdentityFile ~/.ssh/id_rsa

        Now when you ‘ssh target’ OpenSSH will know to first go to client, but when it looks up client, it will know to go to bastion first. At each level, it will pass the appropriate key from you config and use the appropriate settings, prompting you for any additional keys that are needed like 2FA or key passwords.

        In the simplest case, you can just use the shorthand “-J” option: “ssh -J bastion client”
        That will tell SSH to first ssh to bastion, then forward your key to client after. You can specify multiple “-J” entries

        You can also use this with SCP for file transfer through multiple layers, but you have to use the format: scp -o “ProxyJump bastion” file target:/tmp/

    1. I just use the SSH certificate authority support and make sure any new systems I setup trust that CA. Any public key signed by the CA is trusted by the server and will login in the same way as public key authentication. You can of course set expiration and restrict it to certain usernames.

      1. It’s not always that simple, for instance RedHat/CentOS releases often stay on one version while they backport security fixes to that version. So if you use that for your production server it might take a while before you get that feature.

  2. Real magic is sshuttle. That’s quite close to a true VPN, while just working with (almost) any ssh access. I am using that while being in home office, because the official VPN has limited bandwidth. Also you can configure it such that only some internal IP Address range is tunneled, instead of routing the entire traffic through the VPN.

      1. Another great tool is “Dynamic” proxies which are really just SOCKS5 tunnels that work over SSH. You can use Proxychains-ng or redsocks to tunnel most anything in Linux (proxychains-ng also works on OSX).

  3. Another trick without opening a port is to use You can go directly to the server or set up a bastion host. No open port/no IP allow list. Also works in cellular/Satellite CGNAT situations.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.