From 9e96ebb11072d9bb9e2a2698844a97a7fa69136c Mon Sep 17 00:00:00 2001 From: MajorLinux Date: Thu, 30 Apr 2026 05:11:57 -0400 Subject: [PATCH] wiki: add wp-fail2ban logpath on Debian/Ubuntu (auth.log not syslog) Documents the gotcha discovered during the 2026-04-30 DCAProd XML-RPC outage triage: wp-fail2ban plugin emits via PHP syslog(LOG_AUTH) which lands in /var/log/auth.log on Debian/Ubuntu, not /var/log/syslog. wordpress-{hard,soft,extra} jails configured with logpath=/var/log/syslog (common in tutorials and ansible roles) silently catch zero events. Article includes diagnostic steps, the fix, fail2ban-regex verification, distro cheat sheet (Debian/Ubuntu vs RHEL/Fedora vs systemd-journal-only), and a note on why wordpress-login is unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../wp-fail2ban-logpath-debian-ubuntu.md | 151 ++++++++++++++++++ SUMMARY.md | 1 + 2 files changed, 152 insertions(+) create mode 100644 02-selfhosting/security/wp-fail2ban-logpath-debian-ubuntu.md diff --git a/02-selfhosting/security/wp-fail2ban-logpath-debian-ubuntu.md b/02-selfhosting/security/wp-fail2ban-logpath-debian-ubuntu.md new file mode 100644 index 0000000..dcee73f --- /dev/null +++ b/02-selfhosting/security/wp-fail2ban-logpath-debian-ubuntu.md @@ -0,0 +1,151 @@ +--- +title: "wp-fail2ban Plugin Logpath on Debian/Ubuntu (auth.log, not syslog)" +domain: selfhosting +category: security +tags: [fail2ban, wordpress, wp-fail2ban, debugging, gotcha, debian, ubuntu] +status: published +created: 2026-04-30 +updated: 2026-04-30 +--- +# wp-fail2ban Plugin Logpath on Debian/Ubuntu (auth.log, not syslog) + +## The Problem + +You install the [WP fail2ban](https://wordpress.org/plugins/wp-fail2ban/) WordPress plugin, configure the fleet-standard `wordpress-hard`, `wordpress-soft`, and `wordpress-extra` jails, and… nothing. Weeks pass. `fail2ban-client status wordpress-hard` reports `Total failed: 0, Total banned: 0`. Your site is being attacked, but the jails are dead. + +Meanwhile the `wordpress-login` jail (which reads Apache access logs for `POST /wp-login.php` directly) is happily catching brute-forcers. So the problem isn't fail2ban itself — it's specifically the wp-fail2ban-plugin-derived jails. + +## The Cause + +The wp-fail2ban plugin emits events via PHP's `syslog()` call with facility `LOG_AUTH`. On Debian/Ubuntu, rsyslog routes the `auth` facility to **`/var/log/auth.log`**, NOT `/var/log/syslog`. On RHEL/Fedora it's `/var/log/secure`. + +A lot of tutorials, ansible-galaxy roles, and copy-paste config snippets specify: + +```ini +logpath = /var/log/syslog +``` + +That's wrong on Debian/Ubuntu. The events never land there, so the filter regex has nothing to match, so the jail catches zero events forever. Silently. + +## Diagnostic Steps + +If a `wordpress-{hard,soft,extra}` jail shows `Total failed: 0` over a long window despite the plugin being active and the site getting attacked: + +**1. Check what the jail thinks it's watching:** + +```bash +sudo fail2ban-client status wordpress-hard | grep "File list" +``` + +**2. Check where wp-fail2ban events actually land:** + +```bash +sudo grep -c "wordpress(" /var/log/auth.log /var/log/syslog /var/log/secure 2>/dev/null +``` + +You'll see something like: + +``` +/var/log/auth.log:314 +/var/log/syslog:0 +``` + +**3. If the jail's `File list` ≠ the file with events, fix the `logpath`.** + +A real event line on Debian/Ubuntu looks like: + +``` +2026-04-18T23:28:21.027004-04:00 hostname wordpress(example.com)[719989]: XML-RPC authentication failure for someone from 1.2.3.4 +``` + +The `wordpress(domain)[pid]` syslog tag is the giveaway — those are wp-fail2ban events. + +## The Fix + +Edit the jail blocks in `/etc/fail2ban/jail.local` (or your Ansible source for the jail) and set: + +```ini +[wordpress-hard] +enabled = true +port = http,https +filter = wordpress-hard +logpath = /var/log/auth.log +maxretry = 1 +findtime = 60 +bantime = 30d +backend = polling + +[wordpress-soft] +enabled = true +port = http,https +filter = wordpress-soft +logpath = /var/log/auth.log +maxretry = 5 +findtime = 60 +bantime = 30d +backend = polling + +[wordpress-extra] +enabled = true +port = http,https +filter = wordpress-extra +logpath = /var/log/auth.log +maxretry = 5 +findtime = 60 +bantime = 30d +backend = polling +``` + +Then: + +```bash +sudo fail2ban-client -t # validate +sudo fail2ban-client reload +sudo fail2ban-client status wordpress-hard | grep "File list" +# should now show /var/log/auth.log +``` + +## Verification + +You can prove the filter regex actually matches your real events without waiting for an attack — run `fail2ban-regex` against the rotated log: + +```bash +sudo fail2ban-regex /var/log/auth.log.1 /etc/fail2ban/filter.d/wordpress-hard.conf | grep -E "Failregex:|Lines:" +``` + +Healthy output looks like: + +``` +Failregex: 81 total +Lines: 13008 lines, 0 ignored, 81 matched, 12927 missed +``` + +If you see `Failregex: 0 total`, the filter regex doesn't match what the plugin actually emits — which is a different bug (filter version skew vs. plugin version), not the logpath gotcha. Investigate `/etc/fail2ban/filter.d/wordpress-{hard,soft}.conf` against actual event lines. + +> **Note:** On a freshly-fixed jail, counters will sit at `Total failed: 0` for a while — the `polling` backend starts at the file's current EOF, so old events aren't retroactively counted. New events from the moment of `reload` onward will accumulate. Allow a few days of normal attack traffic before declaring the fix broken. + +## Distribution Cheat Sheet + +| Distro family | wp-fail2ban events land in | +|---|---| +| Debian / Ubuntu | `/var/log/auth.log` | +| RHEL / CentOS / Fedora | `/var/log/secure` | +| systemd-journal-only systems | `journalctl SYSLOG_FACILITY=4` (use `backend = systemd` + `journalmatch = SYSLOG_FACILITY=4`) | + +If you have a mixed fleet, parameterize the path: + +```yaml +# Ansible vars +wp_fail2ban_log_path: "{{ '/var/log/auth.log' if ansible_os_family == 'Debian' else '/var/log/secure' }}" +``` + +## Why wordpress-login Is Unaffected + +The `wordpress-login` jail is a different beast — it reads `/var/log/apache2/access.log` directly and matches `^ -.*"POST /wp-login.php` via the `wordpress-login` filter. No plugin involved, no syslog facility involved. So a host can have `wordpress-login` working perfectly while `wordpress-{hard,soft,extra}` are silently dead. Don't let a healthy `wordpress-login` reassure you that the rest of the wp-fail2ban stack is also fine. + +## Related + +- [[fail2ban-wordpress-login-jail]] — the access-log layer that catches WP brute force without any plugin dependency +- [[fail2ban-apache-bad-request-jail]] +- [[fail2ban-apache-php-probe-jail]] +- [[clamav-fleet-deployment]] diff --git a/SUMMARY.md b/SUMMARY.md index 7c20dca..5096c39 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -43,6 +43,7 @@ updated: 2026-04-29T22:45 * [Fail2ban Custom Jail: Apache 404 Scanner Detection](02-selfhosting/security/fail2ban-apache-404-scanner-jail.md) * [Fail2ban Custom Jail: Apache PHP Webshell Probe Detection](02-selfhosting/security/fail2ban-apache-php-probe-jail.md) * [Fail2ban Custom Jail: WordPress Login Brute Force](02-selfhosting/security/fail2ban-wordpress-login-jail.md) + * [wp-fail2ban Plugin Logpath on Debian/Ubuntu (auth.log not syslog)](02-selfhosting/security/wp-fail2ban-logpath-debian-ubuntu.md) * [SELinux: Fixing Fail2ban grep execmem Denial](02-selfhosting/security/selinux-fail2ban-execmem-fix.md) * [UFW Firewall Management](02-selfhosting/security/ufw-firewall-management.md) * [Firewall Hardening with firewalld on Fedora Fleet](02-selfhosting/security/firewalld-fleet-hardening.md)