Home Fun with ssh reverse tunnels
Post
Cancel

Fun with ssh reverse tunnels

How to ssh into a server with a changing ip address

Problem: I have a linux machine behind a firewall, with a changing ip address. I need to be able ssh into it

Solution: Setup a reverse ssh tunnel using autossh and systemd

Network configuration

We have a server with a dynamic ip address hidden behind a firewall. Normally if the server’s ip address was static, we chould first ssh through the jumphost

1
$ ssh user@jumphost.io

And then into the server

1
$ ssh user@serverA

Or in one line using proxy command

1
$ ssh -o ProxyCommand='ssh user@jumphost.io' user@serverA
1
2
3
4
5
6
7
             +------------+            +-----------+
             |            |            |           |
             |   Jumphost |            |  Server A |
             |+----------+|            |           |
  Your +---->++----->----+++----SSH+-->+           |
  Machine    |+----------+|            |           |
             +------------+            +-----------+

However if the ip address of serverA keeps changing, we won’t know what to ssh into for second ssh jump.

There are two possible solutions: 1) Setup a dynamic dns client (only works if ServerA has an ip address directly accessible from the internet) 2) Setup a reverse proxy through a jumphost (works for servers behind a firewall)

Reverse proxy through a jumphost

This involves keeping an live ssh connection from Server A to the Jumphost, leaving an open port tunnel available for reverse ssh.

1
2
3
4
5
6
7
8
             +------------+            +-----------+
             |            |+----SSH+-->|           |
             |   Jumphost |            |  Server A |
             |+----------+|            |           |
  Internet <-++-+PROXY<--++<SSH Tunnel--+          |
             |+----------+|            |           |
             +------------+            +-----------+

Any machine that’s able to ssh into the jumphost, is able to ssh into the server.

Manual Configuration

This can be done manually by:

1) Adding an ssh key so that ServerA can ssh into the Jumphost 2) From Server A

1
$ SSH -NR 10022:127.0.0.1:22 jumphost.io

This sets up a port forwaring from port 10022 on the jumphost to port 22 on ServerA.

It is now possible to access ServerA from the jumphost via port 10022, i.e from jumphost

1
$ ssh -p 10022 user@localhost

Will get you into Server A

Auto-reconnecting the tunnel

The previous tunnel will continue to work untill the connection drops, at which point the tunnel will fail. We can use autossh to keep a connection alive.

From ServerA run:

1
$ autossh -M 0 -o "ExitOnForwardFailure=yes" -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NR 10022:127.0.0.1:22 jumphost.io

The ssh tunnel will now reconnect, should the connection drop.

Keeping the connection live

The auto ssh script can now be added as a systemd process on serverA - this means that the tunnel is started and mainted when serverA reboots.

1) Create a public/private keypair for root user on serverA and add the public key to authorized users on the jumphost.

2) Create the system file

1
$ sudo nano /etc/systemd/system/sshproxy.service

3) Add the following to it

[Unit]
Description=AutoSSH reverse tunnel service for umphost.io 100022 -> 22
After=network.target

[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -o "ExitOnForwardFailure=yes" -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NR 10022:127.0.0.1:22 my.jumphost.io -i /home/root/.ssh/id_rsa

[Install]
WantedBy=multi-user.target

4) Enable the systemd services

1
2
3
$ sudo systemctl daemon-reload
$ systemctl start autossh-jump-rtunnel.service
$ systemctl enable autossh-jump-rtunnel.service
This post is licensed under CC BY 4.0 by the author.