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) <noreply@anthropic.com>
This commit is contained in:
parent
f40f497b46
commit
9e96ebb110
2 changed files with 152 additions and 0 deletions
151
02-selfhosting/security/wp-fail2ban-logpath-debian-ubuntu.md
Normal file
151
02-selfhosting/security/wp-fail2ban-logpath-debian-ubuntu.md
Normal file
|
|
@ -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 `^<HOST> -.*"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]]
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue