How to change the default SSH port (22) and cut automated scanner noise
Learn how to change the default SSH port 22 on Linux safely — sshd_config, UFW firewall, systemd socket, and how to test without locking yourself out of your VPS.
Port 22 is the default target of virtually every automated SSH scanner on the internet. Botnets like Mirai and its variants sweep the entire IPv4 range looking specifically for services exposed on 22 — not because it’s the only possible port, but because it’s the bet with the highest return. Result: even a freshly provisioned VPS accumulates hundreds of failed login attempts per hour in the logs before the first deploy.
Changing the default port isn’t real security against a targeted attacker. A full nmap -p- finds any SSH port in seconds. But the goal here is different: reduce operational noise. Fewer lines in /var/log/auth.log, fewer fail2ban triggers, less CPU spent rejecting obviously malicious connections. In tutorials that recommend this there’s a frequent trap: changing sshd_config alone doesn’t work on modern distros because systemd intercepts the port via socket activation.
This guide takes about 15 minutes and covers the full procedure on Ubuntu 22.04/24.04, Debian 12 and RHEL variants — including the systemd socket adjustment, firewall rules with UFW and firewalld, SELinux configuration when applicable, and the mandatory test before closing the current session.
Prerequisites
Root or sudo access to a Linux VPS, an active SSH session you will not close until the new port is confirmed, and a local SSH client to open a second test connection. Basic knowledge of a text editor (nano or vim).
22/tcp 2222/tcp /etc/ssh/sshd_config ssh.service / sshd.service Keep the current SSH session open throughout the entire procedure. You will open a second connection to test the new port. If something goes wrong, the original session still works as a fallback. Closing before confirming is the most common way to lock yourself out of the VPS.
Choose the new port
The new port must be non-privileged (above 1024) to avoid requiring root for rebinds, and outside the range of well-known services. Recommended range: 1024–49151. Above 49152 is the ephemeral port range, which the kernel uses for outbound connections — it works, but technically competes with dynamic sockets.
Common options: 2200, 2222, 22022, 4422. Avoid ports associated with other services (3306 MySQL, 5432 PostgreSQL, 6379 Redis, 8080 HTTP alternative). For this tutorial we will use 2222 as an example — substitute the value you choose.
Before continuing, confirm the port is free on the server:
sudo ss -tlnp | grep :2222
Expected output: empty. If a process appears, choose another port.
Configure sshd
Back up the current configuration file before any change:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bakIf something breaks, you can restore with sudo cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config and restart the service.
Open the file in your editor:
sudo nano /etc/ssh/sshd_configFind the line with #Port 22 (usually commented by default) and uncomment it, changing to the new port:
Port 2222Save and close. In nano: Ctrl+O, Enter, Ctrl+X.
Validate the sshd_config syntax before restarting — this step prevents the service from failing silently:
sudo sshd -tIf there is no output, the syntax is OK. Any error message indicates a problematic line that needs to be fixed before proceeding.
Adjust the systemd socket (critical step)
On Ubuntu 22.04+, Debian 12+ and some Fedora versions, SSH is activated via systemd socket. This means systemd listens on port 22 and only hands the connection to the daemon when it receives a request. Changing only sshd_config has no effect in this case — the socket stays on 22.
Check if the socket is active:
sudo systemctl status ssh.socketIf Active: active (listening) appears, the socket is controlling the port. If not-found or inactive appears, your distro uses the traditional service and you can skip to step 07.
Disable the socket and use only the traditional service — the cleaner approach that avoids configuration duplication:
sudo systemctl stop ssh.socket
sudo systemctl disable ssh.socket
sudo systemctl mask ssh.socketThe mask prevents other services from activating the socket via dependency. From here on, only sshd_config controls the port.
Make sure the SSH service is enabled for automatic startup:
sudo systemctl enable sshOn RHEL-based distros the service name is sshd instead of ssh — adjust according to your distro.
Open the new port in the firewall
This step needs to happen BEFORE restarting SSH. If you restart first, sshd will start listening on 2222 but the firewall will block connections — and your current session may become unstable during the restart.
If you use UFW (Ubuntu/Debian), allow the new port:
sudo ufw allow 2222/tcp comment 'SSH custom port'Confirm the rule was added:
sudo ufw status numberedDo NOT remove the rule for port 22 yet — do that only after confirming SSH works on 2222.
If you use firewalld (CentOS/Rocky/AlmaLinux/Fedora), use these commands instead:
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reloadOn cloud providers (including Hostini), also confirm there is no security group or external firewall blocking the port. In the Hostini VPS panel, any additional filter rule appears under “Firewall” — add 2222/tcp there if needed.
SELinux (RHEL/CentOS/Rocky/AlmaLinux only)
On distros with SELinux in enforcing mode, the policy prevents sshd from binding to ports not labeled as ssh_port_t. Without this adjustment, the service fails to restart and the error appears in /var/log/audit/audit.log.
Install the port management utility if it isn’t available yet:
sudo dnf install -y policycoreutils-python-utilsOn Debian-based distros SELinux is usually not active, so skip this step. Check with getenforce — if it returns Disabled or the command doesn’t exist, ignore.
Add the new port to the ssh_port_t type:
sudo semanage port -a -t ssh_port_t -p tcp 2222Confirm:
sudo semanage port -l | grep sshExpected output should list 2222 alongside 22 with the ssh_port_t type.
Restart and test
Restart the SSH service:
sudo systemctl restart sshOn RHEL-based: sudo systemctl restart sshd. Confirm it is listening on the new port:
sudo ss -tlnp | grep sshExpected output: a line with LISTEN 0 128 *:2222 *:* (or IPv6 variant). If :22 still appears, the systemd socket was not masked correctly — go back to step 05.
WITHOUT closing the current session, open a NEW local terminal and test the connection on the new port:
ssh -p 2222 user@your_vps_ipIf it connects, great. Keep both sessions open for a few more minutes to confirm stability — only then close the original session.
Do NOT close the original session. Check in this order: firewall (UFW/firewalld), output of ss -tlnp | grep ssh, messages in journalctl -u ssh -n 50. On VPS with an external panel firewall, confirm the port was opened there as well. If nothing solves it, restore the backup and investigate calmly.
Close the old port 22
Only do this step after confirming SSH works stably on 2222 for at least 10 minutes in an independent test session.
sudo ufw delete allow 22/tcp
Or on firewalld:
sudo firewall-cmd --permanent --remove-port=22/tcp
sudo firewall-cmd --reload
Confirm 22 no longer responds:
ss -tlnp | grep :22
Expected output: empty. From here on, any connection on 22 drops immediately at the firewall — exactly the behavior that reduces log noise.
Final verification
Confirm everything at once with a state snapshot:
sudo ss -tlnp | grep ssh
sudo systemctl status ssh
sudo ufw status
You should see: SSH listening only on 2222, service active (running), firewall with 2222/tcp allowed and 22/tcp absent. In 24 hours, compare the volume of failed attempts:
sudo journalctl -u ssh --since '24 hours ago' | grep -c 'Failed password'
Expected drop is 90%+ compared to the exposed 22 — the remainder are scanners that perform a range scan or have already mapped your IP.
Next steps
Changing the port is only the first level of hardening. Recommended next steps:
- Disable password authentication (
PasswordAuthentication noin sshd_config) and use only SSH keys withed25519. - Configure fail2ban with a custom jail for the new port — the package default filter assumes 22 and requires an override.
- Restrict root login:
PermitRootLogin prohibit-password(ornoif you have a sudo user configured). - Enable two-factor authentication via Google Authenticator (
libpam-google-authenticator). - Set up centralized logging to correlate attempts across multiple VPS.
If you’re running this in production, a Hostini VPS comes with native serial console access in the panel — so even if you lock yourself out by a firewall mistake, you can recover access without support. See the options at /vps.
Frequently asked questions
Does changing the SSH port actually improve security?
Not against a targeted attacker — any full scan (nmap -p-) finds the new port in seconds. The real gain is operational: automated botnet scanners only target port 22, so moving to another port cuts 95% of log noise and reduces fail2ban CPU load. It's low-cost hardening, not defense in depth.
Which port should I pick for SSH?
Any non-privileged high port between 1024 and 65535 that doesn't clash with known services. Avoid ports common to other services (3306 MySQL, 5432 Postgres, 8080 HTTP alt). Good options: 2200, 2222, 22022, 49152+. Don't use 222 — it's registered for rsh-spx and corporate firewalls sometimes block it.
Why does my SSH connection still go to port 22 even after I changed sshd_config?
On modern distros (Ubuntu 22.04+, Debian 12+, Fedora) SSH is activated via systemd socket (ssh.socket), which has its own port configuration independent of sshd_config. You need to edit /lib/systemd/system/ssh.socket or mask the socket and use only the service. This is the most common mistake in older tutorials.
How do I find out if any scanner has already discovered my new port?
Count failed auth attempts by port over the last few days: journalctl -u ssh --since '7 days ago' | grep 'Failed password' | wc -l. Compare before and after the change. Expected: a 90%+ drop in volume. If it stays high, an attacker has already mapped the port — consider enforcing key-only auth (PasswordAuthentication no) and fail2ban.
Do I need to reopen port 22 in the firewall later?
No. After confirming SSH works on the new port in another session, explicitly remove the rule for 22: sudo ufw delete allow 22/tcp. Leaving two ports open doubles the attack surface for no real gain. If you need an emergency fallback, prefer the serial console from your VPS panel.
Does SELinux need extra configuration?
Yes, on CentOS/RHEL/Rocky/AlmaLinux with SELinux enforcing. Without this, sshd cannot bind to the new port — the error shows up in /var/log/audit/audit.log. Command: sudo semanage port -a -t ssh_port_t -p tcp 2222. The policycoreutils-python-utils package needs to be installed. On Debian-based distros SELinux is usually not active, so the step doesn't apply.