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
ufw allow <new_port>/tcp first, before touching anything
else.
- Change
Port in sshd_config, restart sshd.
- Open a second session on the new port, without ever closing the first one.
Your current session is your only net.
- 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.