HardStacked
Share:

SSH · attack traffic

1234 login attempts in 41 hours: who really knocks on an exposed SSH port

2026-07-19 · HardStacked · 7 min read

Here is a box nobody is supposed to know about. A fresh IP from a cloud provider, no DNS record, no link pointing at it, nothing published anywhere. One of our ordinary test machines, online for a few days. We pulled its SSH logs on July 20, 2026, covering roughly 41 hours, and counted what had been knocking.

1234 login attempts, every one on an account that does not exist. 93 distinct IP addresses. 132 different usernames. Activity at every single hour of the day. This is not a honeypot study with bait: the box authenticates by key only, and our own connections are excluded from every count below. It is just the ambient noise of the internet, measured.

$ sudo journalctl -u ssh | grep -c 'Invalid user' 1234 ← about 41 hours online. Every one on an account that does not exist.

1. Nobody knew this server existed. It got found anyway

The 93 addresses spread across 61 distinct /16 networks, about 1.5 addresses per network. That dispersion is a signature: this is not one attacker retrying from home, it is a botnet distributed across the world, each member probing a slice of the address space.

Geolocation puts the addresses behind the login attempts in ten countries across four continents. The most insistent one, registered in Iran, knocked 373 times on its own; China, Romania, the United States and Bulgaria fill out the top five. And that map shows where the infected machines sit, not where their operator does.

Nothing « leaked » the server. There was nothing to leak. The IPv4 space is small enough to be swept industrially, and these crews sweep all of it, all the time. Your address is in the space, so your address is on the list. That is the entire targeting logic.

The habit

Treat any machine with a public IP as discovered. Not published, not shared, not in DNS: none of that is a defense, because none of it is how they find you. Obscurity can reduce noise; it cannot be a layer you count on.

2. The username bestiary: 132 names, four kinds of prey

The most interesting artifact in the logs is the list of usernames tried. 132 distinct names in 41 hours, and they read like an inventory of everything that connects to the internet:

$ sudo journalctl -u ssh | grep -oP 'Invalid user \K\S+' | sort | uniq -c | sort -rn | head 410 admin 229 user 125 user2 118 debian 23 test 22 administrator 16 support 14 guest 12 postgres 12 ansible

Sort the full list into families and the botnet's shopping list appears:

The habit

Read that list as the exact set of names not to be. The account you expose over SSH should not be in anyone's dictionary, and service accounts (postgres, www-data…) should have no usable shell and no SSH access at all. An AllowUsers line in sshd_config turns the whole bestiary into instant rejections.

3. Yes, they are hunting Raspberry Pis too

Seven tries on pi, five on orangepi, six on ubnt, five on AdminGPON. The same crew that probes for PostgreSQL servers also probes for your fiber modem and your Raspberry Pi, in the same pass, with the same tooling. They are not looking for « a Linux server »: they rake everything that has an address, using the default account names things ship with.

For years the default on a Raspberry Pi was the pi account with a well-known password, and every botnet dictionary still remembers it. If a Pi at home is port-forwarded so you can reach it remotely, it receives this exact traffic, with a thinner security margin than a server: no one watches a Pi's logs.

The habit

A Pi reachable from outside follows server rules: no pi account, key-only auth, updates applied. If you want to know where yours stands, our open-source audit-pi reads the machine and tells you, free, in one run.

4. It never stops. Ever

819 invalid-user attempts the first full day, 402 the next. And spread out, not in bursts: every single hour of the day saw activity, with the quietest hour still logging around seven attempts. There is no calm window, no time zone where the botnet sleeps, no pattern you could schedule around.

On top of the login attempts, more than a thousand connections opened and closed without ever trying an account. That is the quieter part of the machinery: banner grabs and version scans, the inventory pass that decides which doors are worth pushing on later.

The habit

Accept the noise as the baseline and watch the other line instead:

$ sudo journalctl -u ssh | grep 'Accepted' ← every line here must be you. This is the grep that matters.

A thousand Invalid user lines are Tuesday. One Accepted you do not recognize is an incident.

5. The most beautiful zero in the log

One counter stayed at zero through all of it:

$ sudo journalctl -u ssh | grep -c 'Failed password' 0 ← 1234 attempts, and not one password was ever evaluated.

The box runs PasswordAuthentication no. With key-only auth, sshd rejects these clients before a password is ever exchanged: the guessing engine, the dictionaries, the retries, all of it hits a door with no keyhole. The same 41 hours against a password-enabled box would have produced more than a thousand Failed password lines, each one a real guess against your real password policy.

One honest limit of this data: sshd never logs which passwords were tried, on any configuration. Capturing those takes a deliberate honeypot such as Cowrie, which is a different experiment, for another article.

The habit

PasswordAuthentication no, after testing your key from a second terminal with the current session still open. Done in the wrong order, this is lock-out classic number one; we wrote up the five classic SSH lock-outs and the habits that make them survivable.

Four habits for an internet-facing port

  1. Key-only authentication, tested before you close the door. It is the difference between a thousand real password guesses and the zero above.
  2. No dictionary names exposed. The bestiary is the list of what not to be. AllowUsers with one non-obvious account name rejects the whole inventory.
  3. Watch Accepted, not Invalid user. The noise is the baseline; the exception is the signal.
  4. Obscurity is not a layer. This box had no DNS, no links, an IP never written anywhere. 93 addresses found it regardless.

What this noise is telling you

Everything above is a count from one machine's journal, July 18 to 20, 2026. Your logs will differ in volume, never in nature: the traffic is automatic, indiscriminate and permanent, because it costs the operators nothing and occasionally pays. The question a server owner has to answer is not « will I get probed ». You are being probed right now. The question is whether the configuration holds on the night nobody is watching the logs.

The deeper lesson

The defenses that silenced this whole dataset, key-only auth, no guessable accounts, a hardened SSH block, are exactly the changes people postpone, because touching sshd_config on a remote box feels like sawing the branch you sit on.

That fear is what HardVps removes: it applies the complete SSH hardening block as one reviewed change, captures every original file first, and verifies any restore byte-exact by SHA-256. You get the door that produced our zero, with the way back guaranteed.

See what HardVps does →

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

Share: