Set up public SSH
This chapter will focus on creating an out-of-band backup SSH tunnel (non-WireGuard, non-Traefik based), using a public gateway port on the sentry. This backdoor connection will ensure that you retain access to the Raspberry Pi even during emergency maintenance cycles, including restarting Traefik, restarting Docker, or even rebooting the system (the persistent tunnels will be restarted on boot).
--- title: SSH and wireguard operate independently --- graph TD; S1[SSH client] -->|Public TCP port 2220| SSH W1[Wireguard client] -->|Public UDP port 51820| WG subgraph Docker server SSH[SSH server] WG[Wireguard server] end
Ensure the SSH server is secure
During the rpi-imager
configuration, you should have selected the
option for SSH to Allow public-key authentication only
. You should
double-check that this setting was applied:
cat /etc/ssh/sshd_config | grep "^PasswordAuthentication"
PasswordAuthentication no
If correctly setup, it should show that PasswordAuthentication
is
disabled (thus requring the use of keys rather than passwords).
Open the firewall for SSH (port 2220)
The example TCP port used for the SSH tunnel is 2220
. Make sure you
open this port in the public sentry firewall (i.e., DigitalOcean
firewall).
Install dependencies
AutoSSH is used to create a reliable SSH tunnel.
sudo apt-get update
sudo apt-get install -y autossh
Enable SSH GatewayPorts on the sentry
To expose a public reverse tunnel via SSH, you must enable the non-default GatewayPorts setting in the server’s SSH config, which allows reverse tunnels to be published to the WAN interface of the sentry:
sentry sshd-config GatewayPorts=yes
This will permanently alter the sentry’s /etc/ssh/sshd_config
file
and will then restart sshd
. To restore the setting, run the inverse
command:
## This is the default setting:
sentry sshd-config GatewayPorts=no
With GatewayPorts=no
, the reverse tunnels can only be accessed from
the sentry’s loopback (lo
) interface at 127.0.0.1
, effectively
blocking public access.
Make a one-time transient tunnel
Forward the public sentry port 2220
to the local Raspberry Pi port
22
:
sentry ssh-expose 2220 22
To check the status:
sentry ssh-expose
## Active tunnels: HOST PUBLIC_PORT LOCAL_PORT TYPE ---- ----------- ------------ ---- sentry 2220 22 transient
With the tunnel active, you can ssh to the Pi from anywhere, going through the reverse tunnel public port:
ssh -p 2220 pi@pi.example.com
To stop the service later:
sentry ssh-expose 2220 22 --close
Make a persistent tunnel
To make a persistent connection that will survive a reboot, you must
enable the systemd linger privilege for the pi
user:
sudo loginctl enable-linger ${USER}
To create a persistent connection, use the the --persistent
flag:
sentry ssh-expose 2220 22 --persistent
## Active tunnels: HOST PUBLIC_PORT LOCAL_PORT TYPE ---- ----------- ------------ ---- sentry 2220 22 persistent
Reconfigure SSH clients
On your personal workstation, you can create a new config for accessing the Pi through the public sentry reverse tunnel:
cat <<EOF >> ~/.ssh/config
Host pi.example.com
User pi
Port 2220
ControlMaster auto
ControlPersist yes
ControlPath /tmp/ssh-%u-%r@%h:%p
EOF
Test the public SSH connection to the Pi
ssh -t pi.example.com w
The w
command prints a list of the currently logged in users, and
their remote IP address (-t
is important to ensure the current
connection is included):
18:24:29 up 5 days, 33 min, 1 user, load average: 0.10, 0.07, 0.08 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT ryan pts/2 127.0.0.1 18:24 0.00s 0.01s 0.01s w
Unfortunately there is no way to show the real origin IP address of
the connection; it will always show the IP address of the tunnel
(127.0.0.1
).