Loading...
Home
Explore
Contact
Sign in
Security, Hardening & Backups

Stop Brute Force with fail2ban: SSH & WordPress Jails

Cut most SSH and WordPress login attacks with one tool. Install fail2ban, lock down jails, and verify bans—practical steps for Australian site owners, plus when to book Fixwebnode.

Fixwebnode Support
Fixwebnode Support
11 min read 28 views
Stop Brute Force with fail2ban: SSH & WordPress Jails

If your WordPress site or VPS is hammered by repeated login attempts, fail2ban is the single control that stops most of that noise before it becomes a breach. This guide walks Australian homeowners and small-business owners through installing fail2ban, configuring jails, and enabling SSH plus WordPress protection on a typical Linux host—so you can ban abusive IPs automatically instead of watching auth logs fill up.

At Fixwebnode WordPress Support we harden remote servers for clients across Australia every week. Below is the same practical path we use: real packages, copy-paste commands, verification, and clear points where DIY stops and a specialist should take over.

Why fail2ban matters for WordPress and SSH in Australia

Open SSH and wp-login.php attract constant credential stuffing from global botnets. Australia-based sites are not exempt—attackers scan the whole internet. fail2ban watches log files, matches failed-auth patterns, and updates the firewall (usually iptables or nftables via the firewall backend) so repeat offenders are blocked for a set time. One well-tuned jail set routinely cuts the bulk of automated brute-force traffic without changing your passwords or moving the site.

We work remotely with VPS and cloud hosts used by Australian businesses. Geography does not change the install; what changes is how quickly you notice lockouts, timezone in logs, and whether your host already ships a partial fail2ban package. For where we support clients, see all service areas.

How do we stop most brute-force attacks on WordPress and SSH with fail2ban in Australia?

Install fail2ban from your distro packages, enable the SSH jail, add a filter and jail for WordPress login failures, then reload and confirm bans with fail2ban-client status. That single stack—watch logs, match failures, ban IP—stops the majority of automated password guessing against SSH and wp-login.php without rewriting the site.

Use the table as a quick triage map before you dive into full steps.

SymptomQuick fixWhen to call Fixwebnode
SSH flooded with failed passwordsEnable sshd jail; lower maxretryYou lock yourself out or use non-standard SSH ports/logs
wp-login.php hammered; CPU/spikesWordPress filter + jail on auth logCustom login URL, reverse proxy, or missing log lines
fail2ban running but zero bansCheck filter regex and log pathLog format mismatch after panel/PHP upgrades

Common issues when deploying fail2ban for SSH and WordPress

These are distinct failure modes we see on production boxes—not generic “security tips.”

  • Issue 1 — SSH jail never bans (or bans the wrong traffic): fail2ban-client status sshd shows the jail active but Currently banned stays 0 while /var/log/auth.log (or secure) fills with failures. Often the log path, backend, or sshd log level does not match the stock filter.
  • Issue 2 — WordPress brute force continues after “enabling” fail2ban: Only the default SSH jail is on. There is no filter reading web or PHP logs for “authentication failure” / “Login failed” lines, so wp-login.php and xmlrpc.php stay open to bots.
  • Issue 3 — You lock out legitimate admins (including yourself): Aggressive maxretry / findtime plus shared office NATs or failed SFTP scripts ban your own IP. SSH drops mid-session; WordPress shows repeated blocks from the same office range.
  • Issue 4 — Service fails to start after a config edit: A typo in jail.local or a missing filter file causes fail2ban.service to exit; nothing is protecting the host until fixed.

Install fail2ban (Debian/Ubuntu and RHEL-family)

Prerequisites: root or sudo, a supported Linux VPS, SSH access from a stable IP, and firewall tools already present (iptables, nftables, or firewalld—fail2ban will drive the ban action).

Step 1 — Update packages and install

Debian/Ubuntu:

sudo apt update
sudo apt install -y fail2ban

RHEL, AlmaLinux, Rocky:

sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalld

Step 2 — Enable and start the service

sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban --no-pager

Expect active (running). If the unit failed, jump to the troubleshooting section before adding jails.

Step 3 — Prefer jail.local over editing jail.conf

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Package upgrades overwrite jail.conf; your lasting settings belong in jail.local and drop-in files under /etc/fail2ban/jail.d/.

Configure the jail defaults (the “one setting” baseline)

Global defaults control how aggressive bans are. For most small WordPress hosts we start conservative, then tighten after ignore lists are correct.

Step 1 — Set sensible defaults in jail.local

Under the [DEFAULT] section, set values similar to:

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1
backend = auto
banaction = iptables-multiport

Adjust banaction if your host uses firewalld (firewallcmd-ipset or distro defaults) or nftables. Always add your office or home public IP to ignoreip before lowering maxretry.

Step 2 — Reload and verify defaults loaded

sudo fail2ban-client reload
sudo fail2ban-client get sshd maxretry
sudo fail2ban-client get sshd bantime

If get commands error because sshd is not enabled yet, enable the SSH jail next, then re-check.

Enable SSH protection

Stock filters ship with fail2ban for OpenSSH. Your job is to turn the jail on and point it at the correct auth log.

Step 1 — Confirm where SSH failures are logged

sudo grep -E "Failed password|Invalid user" /var/log/auth.log | tail -n 20
# RHEL-family often uses:
sudo grep -E "Failed password|Invalid user" /var/log/secure | tail -n 20

If those files are empty, check journald-only setups:

sudo journalctl -u ssh -u sshd --since "1 hour ago" | tail -n 50

Step 2 — Enable the sshd jail

In /etc/fail2ban/jail.local or a drop-in:

[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 4
findtime = 10m
bantime = 1h

If SSH listens on a non-standard port, set port = 2222 (example) to match.

Step 3 — Reload and inspect the jail

sudo systemctl reload fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd

You should see the jail listed, a filter name, and eventually banned IPs as failures accumulate.

Step 4 — Manual ban test (safe)

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

Use a documentation-range IP you do not need. Confirm your firewall rules update, then unban.

Enable WordPress protection

WordPress does not ship a fail2ban jail. You add a filter that matches failed logins in the web or PHP log, then a jail that uses it. Two common patterns: (A) auth failures written to the syslog/auth log via a small mu-plugin or host feature, or (B) parsing the web server access/error log for POST storms on wp-login.php and xmlrpc.php. Prefer real authentication-failure lines when you can; access-log rate jails are a fallback.

Step 1 — Decide the log source

If your host or security plugin writes lines like WordPress authentication failure into /var/log/auth.log, use that path. Otherwise use the site access log, for example /var/log/nginx/access.log or the vhost log under /var/log/apache2/.

Step 2 — Create a WordPress filter

sudo nano /etc/fail2ban/filter.d/wordpress.conf

Example filter for syslog-style auth failures (adjust the failregex to match your exact log line):

[Definition]
failregex = ^%(__prefix_line)sWordPress authentication failure.*\s<HOST>
 ^%(__prefix_line)s.*Authentication failure for .* from <HOST>
ignoreregex =

Example fallback filter for nginx access logs (failed POSTs to login endpoints—tune to your log format):

[Definition]
failregex = ^<HOST> -.*"POST /wp-login\.php
 ^<HOST> -.*"POST /xmlrpc\.php
ignoreregex =

Step 3 — Add the WordPress jail

sudo nano /etc/fail2ban/jail.d/wordpress.local
[wordpress]
enabled = true
filter = wordpress
logpath = /var/log/auth.log
backend = auto
maxretry = 5
findtime = 10m
bantime = 1h
port = http,https

If you use the access-log approach, set logpath to the real vhost access log and keep port = http,https.

Step 4 — Test the regex against sample lines

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/wordpress.conf

Or for access logs:

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wordpress.conf

You want a non-zero match count on real failure lines and zero false matches on normal traffic. Fix failregex until that is true.

Step 5 — Reload and confirm the jail

sudo fail2ban-client reload
sudo fail2ban-client status wordpress

Optional: reduce xmlrpc abuse at the application layer as well (disable pingback if unused), but the jail still belongs in fail2ban so repeat offenders hit the firewall.

How to fix each common issue (DIY runbook)

Fix issue 1 — SSH jail active but no bans

  1. Confirm failures exist in the log fail2ban reads (auth.log / secure / journal).
  2. Run sudo fail2ban-regex %(sshd_log)s /etc/fail2ban/filter.d/sshd.conf or point explicitly at the log file path.
  3. In the sshd jail, set logpath explicitly if the default macro is wrong.
  4. Ensure backend matches how logs are written (systemd vs file).
  5. Reload: sudo fail2ban-client reload and re-check status sshd.

Book Fixwebnode when SSH is chrooted, terminated at a bastion, or logs are shipped only to a remote collector so local filters never see failures.

Fix issue 2 — WordPress still under brute force

  1. Verify only sshd is listed in fail2ban-client status; if wordpress is missing, add the filter and jail above.
  2. Confirm failed logins produce lines in the chosen logpath (trigger a failed login from a test browser).
  3. Run fail2ban-regex until matches appear.
  4. Watch sudo tail -f /var/log/fail2ban.log during a test failure for “Ban” lines.
  5. If you use Cloudflare or another reverse proxy, ban the real client IP only if the log shows it—otherwise you may ban the proxy edge. That design needs careful prefer-forwarded / log format work.

Call a pro when login URLs are custom, Multisite paths differ, or PHP runs in containers with logs outside the host path fail2ban watches.

Fix issue 3 — Locked out admins

  1. From console/VNC/host panel (not SSH), add your IP: edit ignoreip in [DEFAULT].
  2. Unban immediately: sudo fail2ban-client unban --all or sudo fail2ban-client set sshd unbanip YOUR.IP.
  3. Raise maxretry slightly and lengthen findtime if a shared NAT serves many staff.
  4. Prefer SSH keys and disable password auth once keys work—fail2ban then sees far fewer legitimate retries.
  5. Document the office IP so future reloads keep ignoreip intact.

If the only access path is SSH and you are already banned with no provider console, you need host-level recovery—Fixwebnode can coordinate that remotely with your VPS provider when you still have panel access.

Fix issue 4 — fail2ban will not start after edits

  1. Check syntax noise: sudo fail2ban-client -t and sudo journalctl -u fail2ban -e --no-pager.
  2. Revert the last jail/filter change; keep a known-good jail.local copy.
  3. Confirm filter file names match the filter = value (no .conf suffix in the jail option).
  4. Start again: sudo systemctl restart fail2ban and verify status.

When configs were heavily customised by a control panel, specialist review avoids fighting the panel’s managed files.

Verification checklist (do this before you walk away)

sudo systemctl is-active fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd
sudo fail2ban-client status wordpress
sudo tail -n 100 /var/log/fail2ban.log

Optionally confirm firewall counters (example for iptables):

sudo iptables -L -n | head -n 80

You want fail2ban chains present and growing ban lists under real attack traffic—not empty jails after a noisy weekend.

When DIY is enough vs when to book Fixwebnode

DIY is enough when you have sudo on a standard Ubuntu/Debian or RHEL-like VPS, stock OpenSSH, a single WordPress vhost with predictable logs, and console access if you misconfigure a ban. Follow the install, jail defaults, SSH, and WordPress sections above, keep ignoreip accurate, and re-check fail2ban-client status weekly at first.

Book Fixwebnode when any of these apply: you already locked out production access; WordPress sits behind Cloudflare/load balancers with complex real-IP headers; logs are only in Docker or a panel path that changes on upgrade; you need coordinated hardening (SSH keys, xmlrpc policy, WAF rules) without downtime; or fail2ban-regex never matches after honest DIY attempts. We are a direct remote WordPress and server specialist for Australian small businesses—not a freelance marketplace—and we work the live host with you.

Talk to Fixwebnode about fail2ban and WordPress hardening

If you want this applied and verified on your server—or you are mid-incident with SSH or wp-login under fire—start a conversation with the team via WordPress Support for Australian small businesses. Bring SSH/panel access details and we will focus on jails, filters, and safe ignore lists so brute-force noise drops without locking out your staff.

Remote delivery covers the full path in this article: install fail2ban, configure jail defaults, enable SSH protection, and add WordPress protection with proof via fail2ban-client status and log matches. That is how we stop the bulk of automated brute-force attacks with one disciplined control plane instead of endless password resets.

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.