Trace SSH Brute-Force Attacks and Cut High Linux CPU Load
Stop SSH brute-force storms draining CPU on Ubuntu/Debian servers. Trace failed logins, harden sshd_config, move off port 22, enforce key-only auth, and know when Fixwebnode should take over remotely in Australia.
If your Linux VPS or dedicated box in Australia is pegged at high CPU while auth logs fill with failed passwords, you are almost certainly under an SSH brute-force loop. This guide walks you through tracing the attackers, blocking them, editing /etc/ssh/sshd_config for a non-standard port and key-only authentication, and verifying that CPU usage drops—without locking yourself out.
Fixwebnode provides direct remote Linux server support for homeowners and small businesses across Australia. When DIY stops being safe, book a specialist session via the Ubuntu Linux server support page rather than guessing under pressure.
Why SSH brute-force attacks spike CPU and break login tracking
Automated bots hammer port 22 with thousands of password guesses per hour. Each attempt wakes sshd, PAM, and often fail2ban or journald. On small cloud instances that load becomes sustained high CPU, slow shells, and noisy logs that hide real problems. Moving ingress off the default port, disabling password auth, and rate-limiting sources is the practical fix path.
How do I stop SSH brute-force attacks causing high CPU on a Linux server in Australia?
Identify the flood in auth logs, block repeat offenders at the firewall, then harden SSH: change the listen port, set PasswordAuthentication no and PubkeyAuthentication yes, reload sshd from a second session, and confirm CPU and failed-login rates fall. If you only have one open session or production depends on the box, hand the change window to a remote specialist.
| Symptom | Quick fix | When to call Fixwebnode |
|---|---|---|
| CPU high; auth.log full of Failed password | fail2ban or ufw deny + review top offenders | Ban list grows faster than you can maintain |
| Legitimate logins slow or time out | Move SSH off 22; key-only auth | Risk of lockout; single session only |
| sshd restarts fail after config edit | sshd -t then fix syntax before reload | Console/out-of-band access unavailable |
Common issues unique to SSH brute-force and CPU spikes
1. Continuous failed-password storms on port 22
Symptoms: journalctl -u ssh or /var/log/auth.log shows repeated “Failed password” and “Invalid user” lines; sshd or kswapd appears in top; load average stays elevated even with idle web apps.
2. Password auth still enabled after “hardening”
Symptoms: keys work but bots still try passwords; CPU never fully settles; cloud provider abuse notices mention SSH scanning.
3. fail2ban or firewall rules thrashing under volume
Symptoms: ban/unban churn, iptables/nftables rule counts explode, short CPU spikes every minute, legitimate office IPs occasionally banned.
4. Accidental lockout after port or PermitRootLogin changes
Symptoms: new SSH sessions refuse connection; only the existing session still works; panic reload loops make CPU worse.
Issue 1 — Trace the brute-force source and measure CPU impact
Confirm the attack before changing production SSH.
Step 1 — Snapshot CPU and sshd
top -b -n 1 | head -n 20
ps aux --sort=-%cpu | head -n 15
systemctl status ssh || systemctl status sshdNote whether sshd, fail2ban, or journald dominate CPU.
Step 2 — Pull failed login patterns
sudo grep -E "Failed password|Invalid user" /var/log/auth.log | tail -n 50
sudo journalctl -u ssh --since "1 hour ago" | grep -E "Failed|Invalid" | tail -n 50
sudo awk '/Failed password/ {print $(NF-3)}' /var/log/auth.log | sort | uniq -c | sort -nr | head -n 20The last command ranks source IPs by failure count (field position can vary slightly by distro; adjust if needed).
Step 3 — Count connection attempts right now
sudo ss -tn state established '( dport = :22 or sport = :22 )' | wc -l
sudo ss -tn state syn-recv '( dport = :22 )' | headHigh SYN-RECV or established counts on 22 support a live scan.
Step 4 — Optional quick block of a top offender (UFW)
sudo ufw deny from 203.0.113.50 to any port 22 proto tcp
sudo ufw status numbered | headReplace the example IP with a real top offender. Prefer fail2ban for ongoing automation (next section).
When logs rotate too fast to read, disk is full, or you cannot tell scanners from staff VPNs, stop and use Fixwebnode remote Linux support.
Issue 2 — Block repeat offenders and calm the auth loop
Install and tune fail2ban so repeated failures earn temporary bans without manual IP whack-a-mole.
Step 1 — Install fail2ban
sudo apt-get update
sudo apt-get install -y fail2ban
sudo systemctl enable --now fail2banStep 2 — Local jail for SSH
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo tee /etc/fail2ban/jail.d/sshd.local > /dev/null <<'EOF'
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 4
findtime = 10m
bantime = 1h
backend = systemd
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status sshdOn some Ubuntu builds logpath is unused when backend = systemd; keep the stanza anyway for clarity. After you change the SSH port later, update port = to the new number or use a comma list.
Step 3 — Verify bans and CPU
sudo fail2ban-client status sshd
top -b -n 1 | head -n 15
sudo journalctl -u ssh --since "10 min ago" | grep -c "Failed password"Failed-password rate should fall within minutes if bans stick.
Step 4 — Whitelist your admin IP
sudo tee -a /etc/fail2ban/jail.d/sshd.local > /dev/null <<'EOF'
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 198.51.100.20
EOF
sudo systemctl restart fail2banUse your real static office or home IP. Dynamic consumer IPs need care or you ban yourself.
Call Fixwebnode if ban lists grow into thousands of entries, nftables/iptables latency appears, or you run a custom SSH port behind Cloudflare Spectrum or a bastion and jail matching breaks.
Issue 3 — Edit sshd_config: non-standard port and key-only auth
This is the core hardening path from the brief. Do it from a second session and never close the working session until a new login succeeds.
Prerequisites
- Your public key already in
~/.ssh/authorized_keysfor the admin user. - Console, VNC, or provider serial access available if possible.
- UFW/security group will allow the new port before you reload sshd.
Step 1 — Confirm key login works on the current port
ssh -i ~/.ssh/id_ed25519 -p 22 admin@YOUR_SERVER_IP
grep -E '^(PasswordAuthentication|PubkeyAuthentication|PermitRootLogin|Port)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* 2>/dev/nullStep 2 — Open the new port on the firewall first
sudo ufw allow 2222/tcp comment 'SSH alternate'
sudo ufw allow OpenSSH
sudo ufw statusPick any high unused port you will remember; 2222 is an example only. Cloud security groups must allow it too.
Step 3 — Write a drop-in config (safer than editing the whole file blind)
sudo mkdir -p /etc/ssh/sshd_config.d
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf > /dev/null <<'EOF'
Port 2222
Protocol 2
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
MaxAuthTries 3
LoginGraceTime 30
AllowUsers admin
X11Forwarding no
AllowTcpForwarding no
ClientAliveInterval 120
ClientAliveCountMax 2
EOFReplace admin with your real sudo user. If root keys are mandatory in your environment, set PermitRootLogin prohibit-password instead of no and understand the risk.
Step 4 — Syntax check before reload
sudo sshd -t
echo $?Exit code 0 means the config parses. Fix any reported line before continuing.
Step 5 — Reload sshd (keep the old session open)
sudo systemctl reload ssh || sudo systemctl reload sshd
sudo systemctl status ssh --no-pager || sudo systemctl status sshd --no-pager
sudo ss -tlnp | grep sshdYou should see sshd listening on 2222 (and possibly still on 22 until a full restart if an old directive remains—remove duplicate Port 22 lines from the main file if needed, then sshd -t and restart).
Step 6 — Test a brand-new session on the new port
ssh -i ~/.ssh/id_ed25519 -p 2222 admin@YOUR_SERVER_IPOnly after this works, close extra sessions and tighten the firewall:
sudo ufw delete allow OpenSSH
sudo ufw allow 2222/tcp
sudo ufw status numberedStep 7 — Point fail2ban at the new port
sudo sed -i 's/^port = ssh/port = 2222/' /etc/fail2ban/jail.d/sshd.local
sudo systemctl restart fail2ban
sudo fail2ban-client status sshdStep 8 — Confirm password auth is dead
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no -p 2222 admin@YOUR_SERVER_IPThis must fail. CPU and auth noise should drop sharply within an hour as bots still hit closed port 22.
Book Fixwebnode when you have only one live session, use nested bastions, or manage fleets where a bad reload means downtime for staff across Australia.
Issue 4 — Reduce leftover CPU load after the attack quiets
Brute-force aftermath can leave journal growth, stuck processes, or misconfigured monitoring.
Step 1 — Re-check resource hogs
top -b -n 1 | head -n 25
sudo journalctl --disk-usage
sudo du -sh /var/log/* | sort -h | tailStep 2 — Vacuum old journals if safe
sudo journalctl --vacuum-time=7d
sudo journalctl --vacuum-size=200MStep 3 — Confirm sshd workers are idle
ps -C sshd -o pid,user,%cpu,%mem,args
sudo ss -tn | grep ':2222' | wc -lStep 4 — Optional unattended-upgrades sanity
sudo apt-get install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgradesKeep kernel and openssh packages patched so tomorrow’s exploit is not today’s CPU incident.
If load remains high with quiet SSH logs, the bottleneck may be PHP-FPM, MySQL, or a compromised process—not SSH. That is a broader performance pass, not more firewall rules.
When DIY is enough vs when to book Fixwebnode
DIY is enough when you already have working key auth, provider console access, a second laptop session, and a non-production or low-traffic window. Follow the numbered steps above, keep the original session open, and verify every reload.
Book Fixwebnode when any of these apply: sole SSH session on a live store; unclear which IP ranges belong to staff; custom SELinux/AppArmor policies; Docker-published SSH; repeated lockouts; or CPU still high after auth storms stop. Fixwebnode works as a direct remote specialist for Linux servers—not a freelance marketplace—covering remote diagnostics for clients across Australia. See where support is offered on the service areas page.
Related build work such as headless WordPress with React/Next.js frontends still depends on a quiet, hardened SSH edge; fix the brute-force CPU loop before chasing application performance.
Book remote help and close the loop
You now have a full path: trace failures, ban repeaters, shift SSH off port 22, enforce key-only passwordless authentication in sshd_config, and re-check CPU. If you want a guided change window or a second pair of eyes before reload, start a conversation with Fixwebnode through the Linux server support landing page. Bring your distro version, current SSH port, and whether console access exists—we will take it from the terminal under pressure with you.