← All posts

Securing a Linux Server with Fail2Ban and a Custom SSH Port

Originally published on Server Mastery - original post, 2023-08-27. Republished here with light edits.

Every server I have ever put online started getting SSH login attempts within hours - long before it had a name, a real user, or anything worth stealing. That is just the internet: bots scan every IP range for port 22, all day, every day. This is the baseline hardening I run on a fresh box before anything else touches it.

Two things, working together:

  • Move SSH off the default port 22, so the dumbest scanners never even find the login prompt.
  • Run Fail2Ban, so anyone who does find it and starts guessing passwords gets banned automatically.

Neither one is a complete security strategy on its own. Together, they remove almost all of the noise from a server's logs.

What you need

Tested on Debian 10 and CentOS 7 at the time of writing, but the steps are the same on any current Debian, Ubuntu, or RHEL-family server - only the package manager command changes.

1. Update the system first

Always start from a fully patched system.

# Debian / Ubuntu
apt-get update && apt-get upgrade && apt-get dist-upgrade

# CentOS / RHEL
yum update

2. Move SSH to a non-default port

Open the SSH daemon config:

nano /etc/ssh/sshd_config

Find the commented-out port line and set your own port instead:

#Port 22
Port 21348

Pick any free port above 1024. Write it down - you will need it for the Fail2Ban config below, and for every future SSH connection to this server (ssh -p 21348 user@server).

3. Install Fail2Ban

apt-get install fail2ban

4. Copy the default config

Never edit jail.conf directly - it gets overwritten on updates. Copy it to jail.local first:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

5. Configure the SSH jail

nano /etc/fail2ban/jail.local

Set a global ban time and retry limit, then point the sshd (and, if relevant, dropbear) jail at your new port:

bantime = 60m
maxretry = 3

[sshd]
enabled = true
mode = aggressive
port = 21348
logpath = %(sshd_log)s
backend = %(sshd_backend)s

[dropbear]
enabled = true
port = 21348
logpath = %(dropbear_log)s
backend = %(dropbear_backend)s

The port line has to match whatever you set in sshd_config - if you forget to update it here, Fail2Ban keeps watching the old port and none of the bans apply to your real one.

6. Save and restart

Save with Ctrl+X, then Y, then Enter in nano, then restart both services so the changes take effect:

systemctl restart sshd
systemctl restart fail2ban

Keep your current SSH session open while you test the new port from a second terminal. If you get locked out because of a typo in sshd_config, the still-open session is what saves you.

Worth adding on top of this

Changing the port and rate-limiting logins cuts out the automated noise, but it is not the whole job. If you are setting this up in 2026, also do these two while you are in there:

  • Disable password authentication entirely once you have an SSH key copied over (PasswordAuthentication no in sshd_config). A banned IP is still an IP that was allowed to guess a password; a key-only server cannot be brute-forced at all.
  • Firewall the port with ufw or firewalld so only the ports you actually use are reachable.

Details anonymised where relevant. Happy to talk through a specific setup - see the contact section on the homepage.

← All posts