HardStacked
Share:

SSH · security by obscurity

Changing your SSH port: what it actually fixes (and what it doesn't)

2026-08-03 · HardStacked · 7 min read

Every few months the same thread shows up on Reddit or Hacker News: should I move SSH off port 22? Half the answers say it's pointless security theater. The other half swear by port 2222. Both sides argue from vibes. We're going to argue from packet captures and auth logs, because we happen to have some.

In July 2026 we left an ordinary Oracle x86 box online with SSH on the default port, key-only authentication (PasswordAuthentication no), and tcpdump listening upstream of the firewall. No bait, no simulated services, just a machine existing on the internet. Here's what the data says about the port debate.

1. What port 22 actually receives

Over 41 hours, the box received 1234 SSH connection attempts. Not scans of the IP, actual authentication attempts against sshd.

Those attempts tried 132 distinct usernames. Note the distinction: 1234 attempts is not 132 attackers trying once each. The same names come back over and over, from different places. The 1234 attempts came from 93 source addresses spread across 61 distinct networks. That distribution pattern, one or two addresses per network, is the signature of a botnet, not of a person. Nobody is sitting at a keyboard targeting you. A distributed machine is grinding through address space.

The list of usernames tells you exactly what that machine is hunting. Four families show up:

Server accounts: admin, postgres, mysql, oracle. DevOps tooling: ansible, deploy, developer, the accounts that hold keys to everything else. Factory credentials for routers, fiber gear and IoT: ubnt, AdminGPON, telecomadmin, huawei. And dev boards: pi, orangepi.

One dictionary, aimed at everything that has an IP address. Your VPS, your neighbor's router, and some abandoned Raspberry Pi behind a forwarded port are all the same job to it. It's not looking for you. It's looking for anything.

One thing you won't find in this data, or in anyone's sshd logs: the passwords tried. sshd never logs the attempted password, only the username and the source. Any article publishing a “top passwords attackers use” got it from a honeypot like Cowrie that simulates authentication to capture credentials. Real auth logs can't produce that list. Worth knowing when you evaluate sources.

2. What moving the port actually does

It cleans your logs. That's the honest, complete answer, and it's not nothing.

The botnet traffic above is bulk scanning. Bulk scanners optimize for coverage per dollar, so most of them hit port 22 and move on. Put sshd on 22000 and the vast majority of that noise never reaches your daemon. Your journal drops from 1234 junk lines in two days to a handful.

Why does that matter if the junk was harmless anyway? Observability. When your log is 99% botnet static, a real event is invisible. A targeted attempt against your actual username, at 3 a.m., from one address, is one line drowned in 1234. On a quiet log, that same line jumps out. Moving the port doesn't make you harder to break into. It makes an actual attack visible when it happens. That's a monitoring gain, and it's real.

The cost is real too. A non-standard port means -p flags in every script, config entries on every client, one more thing to document, and a teammate locked out at the worst moment because nobody told them. On a personal box, cheap. On shared infrastructure, that friction compounds.

3. What it doesn't do

It doesn't hide you. nmap -p- walks all 65535 ports. Internet-wide scanners like the ones behind Shodan and Censys index services on non-standard ports as a matter of course, and sshd cheerfully announces itself with a version banner to anyone who connects. Against bulk background noise, an obscure port filters most of it. Against anyone actually looking at your host, it costs them one scan.

So the security model of “they won't find me on 2222” fails on contact with a full-range scan. If your authentication can't survive being found, the port number was never protecting you. Obscurity as a layer on top of real controls: fine. Obscurity as the control: no.

4. Your auditor pays you 3 points to lock yourself out

Here's the part the forum threads never get to. Your security auditor actively pushes you toward this change. Lynis test SSH-7408 grades the Port directive on a simple logic: anything other than 22 scores better, for a weight of 3 points. On our measurement box in July 2026, after applying 32 fixes, Port was the only SSH suggestion left in the entire report. The tool was literally pointing at one remaining move, and that move was the port change.

And badly executed, that move costs you the machine. Our own firewall fix opens ufw allow 22/tcp and nothing else for SSH. Change Port in sshd_config without opening the new port in the firewall first, on a machine reachable only over SSH, and you have just cut your only way in. The cost is not restarting a service. The cost is reinstalling the machine. This is exactly why we refused to automate the port change in our own product.

If you do it, do it in this order and no other:

The order, and no other

  1. ufw allow <new_port>/tcp first, before touching anything else.
  2. Change Port in sshd_config, restart sshd.
  3. Open a second session on the new port, without ever closing the first one. Your current session is your only net.
  4. Once the reconnection is proven, and only then: ufw delete allow 22/tcp.

Never the reverse. The general rule is bigger than SSH: you remove the old access path only after the new one is proven, and on a remote machine, a session that's already open is the only safety net that exists. There is no console to walk to.

Sit with the irony for a second. The audit score rewards a change that can lock you out of your own server, and stays silent about the one precaution that makes it survivable. That tells you what an audit number actually measures: conformance, not prudence. The checklist knows that port 22 is noisy. It has no idea whether you still have a way back in.

5. What actually works, in order

Here's the part our data proves rather than argues.

Key-only authentication. Across all 1234 attempts on our box, the journal contains zero Failed password lines. Not few. Zero. Every single attempt died as Invalid user or a connection closed before authentication. With PasswordAuthentication no, the botnet never even reached the stage where a password could be tried. Its entire dictionary, all 132 usernames, hit a wall that doesn't care what it guesses. That's what it looks like when a control removes an attack class instead of shrinking it.

PermitRootLogin no. Root is the one username the attacker never has to guess, and the one account where a compromise is instantly total. Take it off the table.

Rate limiting. fail2ban, or nftables connection limits, or sshd's own MaxStartups. Once keys are mandatory, brute force is already dead; rate limiting mostly keeps the noise from wasting your resources and your attention.

Do those three and the port number becomes a question of log hygiene, which is exactly where it belongs.

One practical note before you go check your own logs: on Ubuntu 24.04 minimal cloud images, /var/log/auth.log doesn't exist unless rsyslog is installed. journald is primary. Read journalctl -u ssh, or you'll stare at an empty file and conclude nobody is knocking. They are.

6. The limit of our measurement

Straight up: we measured port 22. We did not run an equivalent box on a high port in parallel, so we have no side-by-side numbers on how much noise a port change sheds. The measured facts are the volume and nature of default-port traffic, and that key-only auth stopped all of it before the password stage. The claim that a high port cuts most bulk noise is reasoning from how mass scanners operate, and we're presenting it as reasoning, not measurement.

The short version

Change the port if you want readable logs. It's a legitimate, minor win. Just don't file it under security, and don't let it stand in for the fix that our 41 hours of data actually validates: keys only, no root login, rate limit the rest.

The deeper lesson

HardVps applies exactly this class of hardening to a VPS, with every change reversible so a config that doesn't fit your setup can be rolled back instead of fought. It's 19.99 USD.

And if you're currently locked out of a box, or not sure what your sshd config actually enforces, write to us. Reading the journal is the easy part once you know which journal to read.

See what HardVps does →

On a Raspberry Pi? Start free with audit-pi, our open-source security audit.

Share: