I have multiple servers and I recently noticed that one of them has a lot more failed ssh login attempts than the others. I only allow public key authentication so I’m not worried that anyone will get in, but it’s still annoying to see that fail2ban regularly bans dozens of IPs. I already run a tarpit on the default ssh port, but it doesn’t take long for attackers to find the port under which the ssh server runs. Some people have something against security by obscurity, but I thought I’d one-up the idea of using a nonstandard port for ssh (or really any other service that doesn’t require a specific port). So instead of using some random port I generate a new one each day via cron job. The port isn’t random but rather follows a random math equation that I also have on my local device. That way I locally also calculate the port for the current day. It sounds stupid and probably also is, but for now it works. I wouldn’t recommend this if ssh is the only way for you to access your server, since this could lock you out if you for some reason can’t get the correct port.
The process is fairly simple. First I wrote a python script for generating the port. I wanted to use pure bash initially, but math is a bit difficult with shell scripts, so I just used python. The script is basically just this:
#!/usr/bin/python3
from datetime import datetime
import math
n = datetime.now()
# Generate a port between 30000 and 32000 from the current date
# The server uses no ports in that range so we can use them freely
d = n.year / 2 + math.sin(n.month ** 2) + n.day
port = int((math.cos(d) + 1) / 2 * 2000) + 30000
print(port)
As you can see it basically just generates a value between zero and one from the current date, multiplies it with the range of ports we want to use (2000) and then adds an offset so the generated ports are between 30000 and 32000. Nothing fancy and if you really wanted you could probably easily reverse engineer the formula after getting a few sequences, but the chance of anyone taking the time to do that is basically zero.
The generated port is then used in a simple shell script that edits the ssh daemon config and restarts the service:
#!/bin/sh
port=$(/path/to/pythonscript)
echo Now running on $port
sed -i "15s/.*/Port $port/" /etc/ssh/sshd_config
systemctl restart sshd
I was too lazy to write proper regex, so this assumes that the configuration
for the port is in line 15 of the sshd_config file. That script just runs a bit
after midnight evert day. On the client I have a script for connecting to the
server, which basically just runs ssh user@server -p $(portshiftscript)
and
that’s basically it. I’ll have to see how that affects the amount of failed login
attempts, but I assume that it’ll make it least a little bit of a difference.