Loading...
Home
Explore
Contact
Sign in
Emergency Fixes & Security

100% CPU Brute Force Outage: Fail2ban and UFW Fix Guide

Site offline with CPU pegged at 100%? Often a brute-force flood. Learn how to diagnose SSH/web attacks, enable Fail2ban and UFW, and when Fixwebnode should take over remotely in Australia.

Fixwebnode Support
Fixwebnode Support
9 min read 9 views
100% CPU Brute Force Outage: Fail2ban and UFW Fix Guide

If your VPS or dedicated box just hit 100% CPU and the whole site went offline, you are not alone—and you should not guess your way through it. This guide is for Australian homeowners and small businesses running Ubuntu or similar Linux servers who need a clear remote path: confirm brute-force load, lock the door with UFW, and stop repeat offenders with Fail2ban before the host throttles or suspends the machine.

Fixwebnode provides direct remote Linux server support for this exact failure mode—not a freelance marketplace. When the attack is still active or DIY steps stall, book a specialist via our Ubuntu Linux server support page. We also cover clients across our listed service areas with remote diagnostics first.

Why a 100% CPU brute-force spike takes the site offline

Brute-force bots hammer SSH, WordPress wp-login, XML-RPC, or panel ports with thousands of auth attempts per minute. Each failed login still costs CPU, disk I/O, and PHP or sshd worker time. Once cores saturate, Nginx/Apache queues grow, MySQL stalls, health checks fail, and visitors see timeouts. Panic reboots without blocking the source IPs only reset the clock—the flood returns in minutes.

The practical response matches what a calm on-call engineer would say: do not panic; identify the flood; enable Fail2ban and UFW to drop the abusive addresses; then verify CPU and site health. The rest of this post walks through unique failure patterns you will actually see on Australian-hosted Linux boxes and the numbered DIY steps that fix them safely over SSH or console.

Is my Australian server offline because of a brute-force attack at 100% CPU?

Yes—if load average and a single service (sshd, php-fpm, or nginx) dominate top while auth logs show rapid failed logins from many IPs, you are almost certainly under a brute-force flood rather than a simple traffic spike. Block with UFW, jail offenders with Fail2ban, then re-check CPU before you restart application stacks.

SymptomQuick fixCall Fixwebnode when
sshd or php-fpm at 100% CPU; auth.log full of failuresUFW rate-limit/deny + Fail2ban sshd/wordpress jailsYou cannot reach SSH or bans do not stick
Site 502/504 while bots hit wp-login or xmlrpcFail2ban filter on access log + temporary location denyCustom app paths or CDN origin still flooded
CPU drops after reboot, then climbs again in minutesPersist UFW rules; enable jails on boot; review open portsRootkit suspicion or unknown listening services

Common issues when CPU hits 100% and the site is offline

These problems look similar on a status page but have different root causes. Treat each distinctly.

1. SSH password spray saturating sshd and the kernel

Symptoms: top shows many sshd processes or high system time; /var/log/auth.log scrolls with “Failed password” and “Invalid user”; legitimate SSH feels sluggish or drops.

2. WordPress or PHP login/XML-RPC flood exhausting php-fpm

Symptoms: php-fpm workers at max, Nginx 502/504, access log filled with POST /wp-login.php or /xmlrpc.php from rotating IPs; database CPU rises from failed auth queries.

3. Wide-open ports and no firewall so scans never stop

Symptoms: UFW inactive; nmap-style connection storms on 22/80/443/3306/2083; CPU recovers briefly after kill -9 then climbs; cloud provider abuse ticket risk.

4. Fail2ban installed but jails misconfigured or not reading the right log

Symptoms: fail2ban-client status shows jails idle; bans never appear; same IPs retry forever; filter regex does not match your log format (journald vs file).

How to fix issue 1 — SSH brute force pegging CPU

Goal: confirm sshd is the burner, rate-limit and ban sources, keep your own admin IP reachable.

Step 1 — Snapshot load and offenders (read-only)

uptime
top -b -n 1 | head -n 25
sudo ss -tnp | grep -E ':22\s' | head
sudo tail -n 100 /var/log/auth.log | grep -E 'Failed password|Invalid user'

If you use journald only:

sudo journalctl -u ssh --since "30 min ago" | grep -E 'Failed password|Invalid user' | tail -n 50

Step 2 — Enable UFW with SSH allowed from your IP first

Replace YOUR.ADMIN.IP with your current public address. Getting this order wrong can lock you out.

sudo apt-get update
sudo apt-get install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from YOUR.ADMIN.IP to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
sudo ufw status verbose

Step 3 — Install and enable Fail2ban for SSH

sudo apt-get install -y fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Create a tight SSH jail override:

sudo tee /etc/fail2ban/jail.d/sshd.local > /dev/null << 'EOF'
[sshd]
enabled = true
port = ssh
filter = sshd
backend = systemd
maxretry = 4
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 ::1 YOUR.ADMIN.IP
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client reload
sudo fail2ban-client status sshd

Step 4 — Verify CPU recovery

sleep 30
uptime
sudo fail2ban-client status sshd
sudo tail -n 20 /var/log/fail2ban.log

You should see banned IPs and a falling load average. If SSH is already unreachable, use your host’s web console or recovery mode before changing UFW.

When to call Fixwebnode: you are locked out, sshd is custom-ported, or bans appear but CPU stays pegged by another process.

How to fix issue 2 — Web login / XML-RPC flood killing PHP

Goal: stop abusive POSTs without taking the whole site down permanently.

Step 1 — Confirm the hot paths

sudo tail -n 200 /var/log/nginx/access.log | awk '{print $1,$7}' | sort | uniq -c | sort -nr | head -n 30
# Apache variant:
# sudo tail -n 200 /var/log/apache2/access.log | awk '{print $1,$7}' | sort | uniq -c | sort -nr | head -n 30
ps aux | grep -E 'php-fpm|apache2|nginx' | head

Step 2 — Temporary Nginx shield for wp-login and xmlrpc

Add inside the server block (adjust paths), then reload:

sudo tee /etc/nginx/snippets/block-wp-brute.conf > /dev/null << 'EOF'
location = /wp-login.php {
 limit_req zone=login burst=5 nodelay;
 try_files $uri =404;
 include fastcgi_params;
 fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
location = /xmlrpc.php { return 403; }
EOF

Ensure a limit zone exists in http context, then test and reload:

sudo nginx -t && sudo systemctl reload nginx
# If php socket name differs, list it:
ls /run/php/

Step 3 — Fail2ban jail against the access log

sudo tee /etc/fail2ban/filter.d/wordpress-login.conf > /dev/null << 'EOF'
[Definition]
failregex = ^<HOST> .* "(POST|GET) /(wp-login\.php|xmlrpc\.php) 
ignoreregex =
EOF
sudo tee /etc/fail2ban/jail.d/wordpress-login.local > /dev/null << 'EOF'
[wordpress-login]
enabled = true
port = http,https
filter = wordpress-login
logpath = /var/log/nginx/access.log
maxretry = 6
findtime = 5m
bantime = 2h
EOF
sudo fail2ban-client reload
sudo fail2ban-client status wordpress-login

Step 4 — Recycle exhausted PHP workers after bans land

sudo systemctl restart php8.2-fpm
# or: sudo systemctl restart php-fpm
curl -sI https://YOUR.DOMAIN/ | head -n 5
uptime

When to call Fixwebnode: the app is not WordPress, logs are behind a reverse proxy with real_ip not set, or only some regions are attacked through a CDN origin.

How to fix issue 3 — No firewall and noisy open ports

Goal: default-deny inbound noise while keeping HTTP/S and your admin path.

Step 1 — See what is listening

sudo ss -tulpn
sudo ufw status verbose || echo "UFW not active"

Step 2 — Close database and panel ports to the world

sudo ufw deny 3306/tcp
sudo ufw deny 5432/tcp
sudo ufw deny 2083/tcp
sudo ufw deny 9090/tcp
sudo ufw status numbered

Step 3 — Optional SSH rate limit if you cannot pin an admin IP

sudo ufw limit 22/tcp
sudo ufw reload

Step 4 — Confirm attack traffic drops

sudo ufw status verbose
watch -n 5 'cat /proc/loadavg; sudo journalctl -u ssh --since "2 min ago" | tail -n 5'

When to call Fixwebnode: you rely on nonstandard ports, Docker-published binds bypass UFW, or the provider firewall and host firewall disagree.

How to fix issue 4 — Fail2ban present but not banning

Goal: make jails actually read logs and insert firewall rules.

Step 1 — Inspect service health

sudo systemctl status fail2ban --no-pager
sudo fail2ban-client status
sudo tail -n 50 /var/log/fail2ban.log

Step 2 — Match backend to how logs are stored

On modern Ubuntu, SSH often needs backend = systemd. Web jails need the real access log path (including sites-enabled custom paths).

sudo fail2ban-client get sshd logpath
sudo fail2ban-regex systemd-journal sshd
# For file-based nginx:
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wordpress-login.conf

Step 3 — Align ban action with UFW

sudo tee /etc/fail2ban/jail.d/00-ufw-action.local > /dev/null << 'EOF'
[DEFAULT]
banaction = ufw
banaction_allports = ufw
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Step 4 — Manual ban test and unban

sudo fail2ban-client set sshd banip 203.0.113.50
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.50

If manual bans work but automatic ones do not, the filter or logpath is wrong—not the firewall.

When to call Fixwebnode: nftables/iptables conflict, jail starts then stops, or SELinux/AppArmor-style denials block the ban action (less common on stock Ubuntu cloud images).

When DIY is enough vs when to book Fixwebnode

DIY is enough when you still have console or SSH access, UFW rules accept your admin IP, Fail2ban shows active bans, load average trends down within 10–15 minutes, and HTTP starts returning 200/301 again. Document the banned ranges and consider key-only SSH next maintenance window.

Book Fixwebnode when any of these are true: the site is offline and you cannot log in; CPU stays at 100% after jails are online; malware or unknown miners appear in top; Docker/Kubernetes publishing bypasses the host firewall; or you need a durable hardening pass (key-only SSH, automatic security updates, log shipping) without trial-and-error on a live shop. Remote work is the default delivery mode for this incident type across Australia—we diagnose over secure session and provider console when needed, as a direct specialist team via Linux server support with Fixwebnode.

Stabilise the box, then talk to a specialist

A 100% CPU outage from brute force is frightening, but the path is orderly: measure which process burns the cores, deny the noise with UFW, jail repeat offenders with Fail2ban, reload web/PHP only after bans land, and verify with load average and a simple curl. If you want that done with you on the line—or already lost SSH—start a conversation through our landing page for Ubuntu Linux server support and bug fixing. For geographic coverage notes only, see all service areas. Bring your provider console access and approximate outage start time so we can stop the flood and bring the site back cleanly.

Share this article
Fixwebnode Support
Fixwebnode Support

Hey there!
I am your assistant for Fixwebnode. Ask about our services, quotes, packages, orders, or how to get support.
While you wait
What’s your name and best email? We’ll reply even if you leave.