Symptoms
You SSH into sw-infrarunbook-01 to check on something unrelated, run a quick
tail /var/log/auth.logout of habit, and there it is again: a wall of failed login attempts, most of them for users that don't exist on the box. Sometimes it's a slow trickle, a handful of attempts an hour from different countries. Other times it's a flood, hundreds of attempts a minute from a single subnet, all trying variations of admin, root, and oracle. Either way, once you notice it, you can't unsee it.
In my experience, this is one of the most common tickets that gets filed and then immediately dismissed as noise. Sometimes that dismissal is correct. Sometimes it isn't. The trouble is that repeated unauthorized login attempts can mean anything from routine internet background radiation to an active, targeted attack against a specific account that's about to succeed. The log line looks the same either way:
Aug 25 03:14:02 sw-infrarunbook-01 sshd[19823]: Failed password for invalid user admin from 198.51.100.44 port 51322 ssh2
Aug 25 03:14:05 sw-infrarunbook-01 sshd[19825]: Failed password for root from 198.51.100.44 port 51410 ssh2
Aug 25 03:14:09 sw-infrarunbook-01 sshd[19827]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=198.51.100.44 user=rootOther symptoms that usually show up alongside this: elevated CPU on the box from spawned sshd processes, fail2ban (if it's installed) constantly banning and unbanning the same handful of IP ranges, alerting tools flagging a spike in auth failures, and occasionally a support request from a legitimate user saying "I can't log in, it says too many attempts." Let's go through the actual causes, one at a time, and how to tell them apart.
Cause 1: Mass internet scanning (the default explanation, and usually the right one)
The overwhelming majority of unauthorized login attempts against internet-facing servers have nothing to do with you specifically. Botnets and research scanners (Shodan-adjacent crawlers, university projects, and plenty of outright malicious infrastructure) constantly sweep the entire IPv4 address space looking for open port 22, port 3389, or exposed database ports. If your server has a public IP and SSH listening on the default port, you will get scanned within hours of it going live, guaranteed.
You can confirm this pattern by looking at the diversity of source IPs and usernames being tried:
grep 'Failed password' /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20If you see dozens of distinct IPs, each only trying a handful of times, and usernames like admin, test, oracle, ubuntu, pi, and postgres, that's textbook mass scanning. Nobody is targeting sw-infrarunbook-01 specifically; they're targeting the entire internet and your server happened to answer.
The fix here isn't really a "fix" for the scanning itself; you can't stop the internet from scanning you. Instead, you reduce the attack surface. Move SSH off port 22:
sudo sed -i 's/^#Port 22/Port 22022/' /etc/ssh/sshd_config
sudo systemctl restart sshdThis won't stop a determined attacker, but it drops the volume of automated noise by well over 90% in most environments I've managed, since most scanners only check the default port. Pair it with fail2ban so that even the reduced volume gets automatically banned after a few attempts.
Cause 2: Credential stuffing against known usernames
This is a step up from generic scanning. Here the attacker already has a list of usernames, often scraped from a data breach unrelated to your infrastructure, and is trying those specific usernames with common or previously-leaked passwords across many servers. You'll notice the same real-looking usernames (not "admin" or "root" but things like actual employee names or your infrastructure-admin naming convention) recurring across attempts.
grep 'Failed password' /var/log/auth.log | grep -v 'invalid user' | awk '{print $9}' | sort | uniq -c | sort -rnIf you run this and see a valid, existing account like infrarunbook-admin showing up repeatedly with failed attempts (not "invalid user," meaning the account actually exists on the box), that's a real threat, not noise. Someone either found this username in a breach dump or guessed it from your naming pattern.
Aug 25 04:02:11 sw-infrarunbook-01 sshd[20011]: Failed password for infrarunbook-admin from 203.0.113.77 port 44012 ssh2Fix: rotate the password or, better, disable password auth for that account entirely and force key-based authentication. Check whether that username or its password pattern appears in any known breach corpus you have access to internally, and if the same password is reused anywhere else, treat all those systems as potentially compromised.
Cause 3: A leaked or weak SSH key, not a password
People assume "unauthorized login attempts" means password guessing, but I've seen plenty of cases where the log shows repeated connection attempts that get past the initial handshake and fail at key exchange or key verification instead:
Aug 25 05:10:44 sw-infrarunbook-01 sshd[20233]: Connection closed by authenticating user infrarunbook-admin 192.0.2.150 port 39211 [preauth]
Aug 25 05:10:47 sw-infrarunbook-01 sshd[20235]: error: maximum authentication attempts exceeded for infrarunbook-admin from 192.0.2.150 port 39218 ssh2 [preauth]This pattern, especially "maximum authentication attempts exceeded," often means someone has a list of stolen or generated private keys and is trying them one after another against your server, because your public key infrastructure (an authorized_keys file, a CI system, a shared bastion) leaked somewhere. Check who has valid keys authorized on the box and cross-reference with recent key rotations:
cat /home/infrarunbook-admin/.ssh/authorized_keys | wc -l
sudo find / -name authorized_keys -exec ls -la {} \;If you find keys you don't recognize, or an authorized_keys file with a suspiciously recent modification time, that's your answer. Fix: strip unrecognized keys immediately, rotate the legitimate ones, and lock down permissions (chmod 600 on the file, 700 on .ssh).
Cause 4: A compromised host on your own network scanning laterally
This one gets missed constantly because people assume "unauthorized login attempts" always means external attackers. Sometimes the source IP is inside your own RFC 1918 range:
Aug 25 06:33:19 sw-infrarunbook-01 sshd[20599]: Failed password for root from 10.20.4.17 port 55210 ssh2
Aug 25 06:33:22 sw-infrarunbook-01 sshd[20601]: Failed password for admin from 10.20.4.17 port 55214 ssh2If 10.20.4.17 is a machine you know isn't supposed to be initiating SSH connections to this box, this is a serious signal that the source host itself has been compromised and is now trying to pivot laterally. I've walked into this exact situation before: an internal monitoring VM got popped through an unpatched web app, and it started brute-forcing every other host on the subnet within minutes.
Fix: isolate the source host from the network immediately, don't just block it at the firewall on the destination side, because it's likely also attacking other machines you haven't checked yet. Investigate that host separately as its own incident.
sudo iptables -A INPUT -s 10.20.4.17 -j DROP
# then go quarantine and investigate 10.20.4.17 itselfCause 5: Misconfigured application or cron job hammering its own auth
Not everything that looks like an attack is one. I've spent an embarrassing amount of time once chasing what looked like a brute-force pattern, only to discover it was a cron job on another server with a stale, incorrect password in its config, retrying an SSH-based backup sync every five minutes.
Aug 25 02:00:01 sw-infrarunbook-01 sshd[18211]: Failed password for backup-svc from 172.16.8.30 port 60122 ssh2
Aug 25 02:05:01 sw-infrarunbook-01 sshd[18344]: Failed password for backup-svc from 172.16.8.30 port 60310 ssh2
Aug 25 02:10:01 sw-infrarunbook-01 sshd[18477]: Failed password for backup-svc from 172.16.8.30 port 60501 ssh2The giveaway is the suspiciously exact timing interval. Real attackers don't usually retry every five minutes on the dot for days; scripts and cron jobs do. Check the source machine's crontab and any systemd timers for scheduled jobs that touch this host:
crontab -l -u backup-svc
sudo systemctl list-timers --allFix: update the stale credential or, better, switch that job to key-based auth so a rotated password can never cause this again.
Cause 6: Exposed non-SSH services with their own auth (RDP, database ports, web admin panels)
SSH gets all the attention, but the same pattern shows up against any exposed authentication surface: RDP on Windows boxes, MySQL or PostgreSQL bound to 0.0.0.0, phpMyAdmin, or a web app's admin login. Check what's actually listening publicly before you assume this is purely an SSH problem:
sudo ss -tulnp | grep LISTENtcp LISTEN 0 128 0.0.0.0:3306 0.0.0.0:* users:(("mysqld",pid=1122,fd=23))
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=901,fd=3))Seeing MySQL bound to 0.0.0.0 instead of 127.0.0.1 is a red flag by itself, regardless of whether you've noticed failed logins against it yet. Check the database's own auth log too:
grep 'Access denied' /var/log/mysql/error.log | tail -30Fix: bind the service to localhost or an internal-only interface, put it behind a VPN or bastion, and use a firewall rule restricting the port to known source ranges rather than relying on the application's own password checks as your only line of defense.
Cause 7: Root login enabled over SSH
This isn't a cause of the attempts themselves, but it massively raises the stakes of every other cause on this list. If PermitRootLogin is still enabled, every attempt against "root" isn't just noise, it's a direct shot at the most privileged account on the box, and attackers know this account exists on every Linux server without having to guess a username.
sudo sshd -T | grep permitrootloginIf that comes back as anything other than "no," fix it now:
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl restart sshdAlways run
sshd -tto test the config before restarting; a syntax error here locks you out of remote access to the box entirely, which is a bad time to discover you don't have console access.
Cause 8: Log noise from IPv6 or dual-stack misreads inflating the count
A subtler one I've run into on dual-stack hosts: monitoring tools sometimes double-count attempts because the same client hits both the IPv4 and IPv6 listener, or because a load balancer health check with a slightly misconfigured probe gets logged as a failed auth attempt. Before escalating a spike as an active attack, verify the actual attempt count against what your alerting tool reported:
grep 'Failed password' /var/log/auth.log | wc -l
journalctl -u sshd --since "1 hour ago" | grep -c 'Failed password'If these two numbers disagree significantly, or if your monitoring dashboard is reporting a number way higher than either, the alerting pipeline itself might be the thing that's broken, not your server's security posture. I've chased false alarms before that turned out to be a Filebeat config double-shipping the same log file.
Prevention
You will never make repeated login attempts stop entirely; as long as a server has a public IP, someone somewhere is going to knock on the door. What you can control is whether those attempts have any chance of succeeding, and how fast you notice when the pattern changes from background noise to something targeted.
Disable password authentication for SSH entirely and require keys:
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart sshdInstall and tune fail2ban so that repeat offenders get banned automatically instead of relying on you noticing manually:
sudo apt install fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshdRestrict SSH access at the firewall level to known source ranges wherever possible, rather than leaving it open to the entire internet. Rotate keys and audit authorized_keys files on a schedule, not just when something looks wrong. Move any exposed database or admin service off the public interface and behind a VPN. And keep an eye on the baseline: know roughly how many failed attempts per day is "normal" for your environment so you can actually tell when something has changed, instead of treating every log entry as either a non-event or a five-alarm fire.
Most of all, don't let repeated unauthorized login attempts become wallpaper. The scanning noise is real and mostly harmless, but it's also the exact camouflage a targeted attempt against a real account will hide inside. Check the usernames, check whether the account exists, check where the source IP actually sits, and you'll know within a couple of minutes which of these eight situations you're actually looking at.
