RT Cunningham

Blogging For As Long As I'm Able

My Extra Secure SSH Setup

Tagged with computers, linux, raspberry pi, ssh, vnc, x2go on May 2, 2024

Extra Secure SSH Although normal life has been getting in the way, I finally figured out how to make my “server” as secure as it can be. I’ve set things up so I can only connect to my Raspberry Pi 400 (“Pi” for short) from one external IP address using the Secure Shell Protocol (SSH). That IP address will come from my laptop computer, regardless of where I am in the world.

Remote Services on the Pi

There are only two services I will regularly use when I need to access the Pi. The first is SSH, for command line routines, and the second is the X2Go server, for graphical routines. The X2Go client connects by SSH, as does rsync. I’m leaving the VNC service running as a backup, since I can only connect to it with RealVNC’s cloud service.

The only reason I wanted to use a VPN was to tie SSH to one IP address, but I couldn’t get it to work right. I subsequently found a more elegant solution, so I removed the VPN.

SSH Was Already Secure

I was already using best practices with SSH:

I even moved the port number to avoid the simple scanners. Still, seeing the attempted connections to the port I moved it to continued to irritate me. I simply had to block all those IP addresses in a way that made sense.

Extra Secure SSH

The Pi’s IP address is tied to duckdns.org, a dynamic subdomain service. I tied the laptop computer’s IP address to duckdns as well and adapted a routine I found at a couple of Linux forums. The routine runs on the Pi. Here’s the BASH script, which I call access.sh, with some things changed to protect my connection. It has to be run as root (sudo) because it adds and deletes firewall rules:

#!/bin/bash
HOSTNAME=sub.domain.dom
IPFILE=/home/username/access.txt
Current_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')
if [ ! -f $IPFILE ]; then
    /usr/sbin/ufw allow from $Current_IP to any port 22 proto tcp
    echo $Current_IP > $IPFILE
else
    Old_IP=$(cat $IPFILE)
    if [ "$Current_IP" = "$Old_IP" ] ; then
        echo IP address has not changed
    else
        /usr/sbin/ufw delete allow from $Old_IP to any port 22 proto tcp
        /usr/sbin/ufw allow from $Current_IP to any port 22 proto tcp
        echo $Current_IP > $IPFILE
        echo iptables have been updated
    fi
fi

The firewall denies all incoming connections except the one allowed by a single rule. I’ve been letting this script run as a root level cron job (sudo crontab -e) for a couple of days (every five minutes), and it hasn’t failed to work properly. The IP address changed yesterday morning due to a one-hour power outage.

Again, I’m leaving the VNC service running as a backup. That’s just in case this script stops working or something else out of my control happens.

Image by Jessie Kirk, CC BY 4.0, via Wikimedia Commons

← Previous ArticleNext Article →