Almost every automated SSH scan on the Internet targets port 22. Moving SSH to another port does not make the server more secure against a targeted attack, but it removes most of the brute-force noise from your logs and from Fail2Ban. In this tutorial you will add a new SSH port alongside port 22, open it in the firewall (and in SELinux on Rocky Linux), test it, and only then close port 22. The steps cover Ubuntu 24.04, which uses systemd socket activation for SSH, as well as Debian 12 and Rocky Linux 9.

Prerequisites

To follow this guide you need:

  • A server running Ubuntu 24.04 LTS, Debian 12 or Rocky Linux 9, for example a CubePath VPS.
  • A non-root user with sudo privileges and working SSH access.
  • Access to the server's web console (on CubePath, the VNC console in the dashboard). If something goes wrong, it is your way back in.

This guide uses port 2222 as an example. Replace it with your own your_port everywhere.

Step 1 - Choosing a free port

Pick a port between 1024 and 65535 that no other service on the server uses and that your own network allows outbound (some corporate and hotel networks block unusual ports). Check that nothing listens on it yet:

sudo ss -tlnp | grep ':2222 '

No output means the port is free. Also check that no Port directive is already set elsewhere, since you will add yours to the main file:

sudo grep -Rni '^ *Port ' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/

If this prints a line, change the port in that file instead of adding a new one.

Step 2 - Adding the new port to the SSH configuration

Back up the configuration first:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

Open the main configuration file:

sudo nano /etc/ssh/sshd_config

Find the commented line #Port 22 near the top. Replace it with two lines, so SSH listens on both ports during the transition:

Port 22
Port 2222

Save the file and check the syntax. sshd -t prints nothing if the file is valid:

sudo sshd -t

Nothing changes until you restart the service in Step 5, so first make sure the new port will be reachable.

Step 3 - Allowing the port in the firewall

Open the new port before SSH starts listening on it.

Ubuntu and Debian with UFW

sudo ufw allow 2222/tcp comment 'SSH'
sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
2222/tcp                   ALLOW       Anywhere                   # SSH
OpenSSH (v6)               ALLOW       Anywhere (v6)
2222/tcp (v6)              ALLOW       Anywhere (v6)              # SSH

If UFW shows Status: inactive, the rule is stored and will apply when you enable UFW.

Rocky Linux with firewalld

sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports
2222/tcp

Step 4 - Allowing the port in SELinux (Rocky Linux only)

On Rocky Linux, SELinux only lets sshd bind to ports labelled ssh_port_t. Without this step the service fails to start on the new port with a Permission denied error. Skip it on Ubuntu and Debian.

Install the semanage tool if it is missing and add the label:

sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222

If the port already belongs to another SELinux type, -a fails with already defined. In that case modify it instead with sudo semanage port -m -t ssh_port_t -p tcp 2222.

Verify:

sudo semanage port -l | grep ssh_port_t
ssh_port_t                     tcp      2222, 22

Step 5 - Restarting SSH

How you apply the change depends on the distribution.

Ubuntu 24.04

Ubuntu 24.04 starts SSH through socket activation: systemd, not sshd, owns the listening socket in ssh.socket, and a generator creates the socket's port list from sshd_config. Check whether your server uses it:

systemctl is-active ssh.socket

If the answer is active, regenerate the socket configuration and restart the socket:

sudo systemctl daemon-reload
sudo systemctl restart ssh.socket

If the answer is inactive (some images disable socket activation), restart the service instead:

sudo systemctl restart ssh

Debian 12

sudo systemctl restart ssh

Rocky Linux 9

sudo systemctl restart sshd

Now confirm that SSH listens on both ports:

sudo ss -tlnp | grep -E ':(22|2222) '
LISTEN 0      4096         0.0.0.0:22        0.0.0.0:*    users:(("sshd",pid=1021,fd=3),("systemd",pid=1,fd=86))
LISTEN 0      4096         0.0.0.0:2222      0.0.0.0:*    users:(("sshd",pid=1021,fd=4),("systemd",pid=1,fd=87))
LISTEN 0      4096            [::]:22           [::]:*    users:(("sshd",pid=1021,fd=5),("systemd",pid=1,fd=88))
LISTEN 0      4096            [::]:2222         [::]:*    users:(("sshd",pid=1021,fd=6),("systemd",pid=1,fd=89))

The process names differ between distributions (on Debian and Rocky Linux only sshd appears). What matters is that both ports are listed.

Step 6 - Testing the new port

From a new terminal on your local computer, connect on the new port:

ssh -p 2222 your_user@your_server_ip

The first connection on a new port may ask you to confirm the host key again. The key itself has not changed, so the fingerprint is the same one you accepted before. Continue only when you get a shell.

If the connection times out, the firewall is still blocking the port. If it is refused, SSH is not listening on it. See Troubleshooting before going further.

Step 7 - Closing port 22

With the new port confirmed, remove port 22 from SSH. Open the configuration again:

sudo nano /etc/ssh/sshd_config

Delete the Port 22 line and keep only:

Port 2222

Check the syntax:

sudo sshd -t

Apply the change with the same command you used in Step 5. On Ubuntu 24.04 with socket activation that is:

sudo systemctl daemon-reload
sudo systemctl restart ssh.socket

On Debian 12 (or Ubuntu without socket activation) run sudo systemctl restart ssh, and on Rocky Linux sudo systemctl restart sshd.

Then remove the old firewall rule.

On Ubuntu and Debian:

sudo ufw delete allow OpenSSH
sudo ufw status

If you had created the rule as ufw limit OpenSSH, delete it with sudo ufw delete limit OpenSSH instead.

On Rocky Linux:

sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Leave the 22 entry in the SELinux ssh_port_t list: it is part of the base policy and cannot be removed.

Confirm that SSH now listens only on the new port, and test once more from a new local terminal:

sudo ss -tlnp | grep sshd
ssh -p 2222 your_user@your_server_ip

Step 8 - Updating Fail2Ban

If you run Fail2Ban, its sshd jail bans addresses on port 22 by default, so bans would not affect the new port. Open your local jail configuration:

sudo nano /etc/fail2ban/jail.local

Add the port to the [sshd] section:

[sshd]
enabled = true
port = 2222

Restart Fail2Ban and confirm the jail is running:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Step 9 - Updating your SSH client

Typing -p 2222 every time is easy to forget. Save the port in your local ~/.ssh/config:

nano ~/.ssh/config
Host myserver
    HostName your_server_ip
    User your_user
    Port 2222

Now ssh myserver uses the right port, and so do tools that go through SSH:

scp ./file.txt myserver:/tmp/
rsync -avz ./site/ myserver:/var/www/site/

When you do not use an alias, remember that scp takes the port with a capital -P (scp -P 2222 ...) and rsync needs -e "ssh -p 2222".

Troubleshooting

SSH still listens only on port 22 on Ubuntu 24.04: the socket was not regenerated. Run sudo systemctl daemon-reload and sudo systemctl restart ssh.socket, then check with systemctl cat ssh.socket that the generated drop-in lists your port.

Connection timed out on the new port: the firewall is dropping it. Check sudo ufw status or sudo firewall-cmd --list-ports. If your provider or network has a firewall in front of the server, allow the port there as well.

sshd fails to start on Rocky Linux: look at the error with sudo journalctl -u sshd -n 20. error: Bind to port 2222 on 0.0.0.0 failed: Permission denied means the SELinux label from Step 4 is missing.

Locked out completely: log in through the web console and restore the backup, then restart SSH as in Step 5:

sudo cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config

Make sure port 22 is allowed again in the firewall (sudo ufw allow OpenSSH or sudo firewall-cmd --permanent --add-service=ssh followed by --reload).

Conclusion

SSH now listens only on your custom port, the firewall and SELinux allow it, Fail2Ban watches the right port, and your client knows how to connect. Keep in mind that a port change only reduces noise: the real protection comes from key-only authentication, disabled root login and Fail2Ban. Good next steps are disabling password logins if you have not yet, restricting SSH in the firewall to your own IP ranges where possible, and reviewing journalctl -u ssh periodically for unexpected logins.