Wordpress
To protect a WordPress Docker container using Fail2ban, you need to create a custom filter that detects malicious activity, such as brute-force login attempts, by analyzing the web server logs. Since WordPress is often deployed behind a reverse proxy like Nginx Proxy Manager (NPM) in a Docker environment, the filter should target patterns in the access logs that indicate failed login attempts. Below are detailed suggestions for crafting an effective Fail2ban filter and setting it up to secure your WordPress instance.
Suggested Filter for WordPress
The primary goal is to detect failed login attempts to the WordPress admin login page (/wp-login.php). In WordPress, a failed login attempt often results in a redirect to /wp-login.php?login=failed, which can be observed in the web server access logs. This pattern can be used to identify potential brute-force attacks.
- Filter Definition
Create a custom Fail2ban filter to match this pattern. Here's a suggested configuration:
-
File Location: /etc/fail2ban/filter.d/wordpress-login.conf
-
Content:
ini
[Definition] failregex = ^<HOST> - - \[.*\] "GET /wp-login\.php\?login=failed .*"$ ignoreregex = -
Explanation:
-
^
: Matches the client IP address at the start of the log line, which Fail2ban uses to ban the offending IP. -
- - \textbackslash[.*\textbackslash]: Skips the user and timestamp fields in the log (common in access log formats). -
"GET /wp-login\textbackslash.php\textbackslash?login=failed .*": Matches GET requests to /wp-login.php?login=failed, indicating a failed login attempt. The \ escapes the . and ? characters, which are special in regular expressions.
-
$: Ensures the pattern matches the end of the request string.
-
This filter assumes a standard web server log format (e.g., Nginx combined or Apache common log format), such as:
192.168.1.1 - - [10/Oct/2023:13:55:36 +0000] "GET /wp-login.php?login=failed HTTP/1.1" 200 1234- Jail Configuration
To use the filter, you need to define a Fail2ban jail that specifies the log file to monitor and the banning rules. Here's a suggestion:
-
File Location: /etc/fail2ban/jail.d/wordpress.conf
-
Content:
ini
[wordpress-login] enabled = true filter = wordpress-login logpath = /dockge/npm/data/logs/proxy_host_1_access.log maxretry = 5 findtime = 600 bantime = 3600 port = http,https -
Explanation:
-
enabled = true: Activates the jail.
-
filter = wordpress-login: Links to the custom filter defined above.
-
logpath: Specifies the path to the WordPress access log. If your WordPress container is behind NPM, this might be an NPM proxy host log (e.g., /dockge/npm/data/logs/proxy_host_1_access.log). Adjust this path based on your setup.
-
maxretry = 5: Bans an IP after 5 failed attempts.
-
findtime = 600: Looks for those 5 attempts within 10 minutes (600 seconds).
-
bantime = 3600: Bans the IP for 1 hour (3600 seconds).
-
port = http,https: Protects traffic on ports 80 and 443.
-
Implementation Steps
-
Locate the Access Log:
-
Determine where your WordPress access logs are stored. If using NPM as a reverse proxy, check the logs directory (e.g., /dockge/npm/data/logs/) for a file specific to your WordPress proxy host (e.g., proxy_host_1_access.log).
-
If monitoring the WordPress container directly, ensure its logs are accessible on the host (e.g., via a Docker volume mount like /var/log/nginx/access.log).
-
-
Create the Filter:
-
Use a text editor to create the filter file:
bash
sudo nano /etc/fail2ban/filter.d/wordpress-login.conf -
Paste the filter content provided above and save.
-
-
Set Up the Jail:
-
Create the jail file:
bash
sudo nano /etc/fail2ban/jail.d/wordpress.conf -
Paste the jail content, adjusting the logpath to match your environment, and save.
-
-
Apply the Configuration:
-
Restart Fail2ban to load the new settings:
bash
sudo systemctl restart fail2ban -
Verify the jail is running:
bash
sudo fail2ban-client status wordpress-login
-
-
Test and Monitor:
-
Simulate failed logins to /wp-login.php and check the Fail2ban log for bans:
bash
sudo tail -f /var/log/fail2ban.log
-
Additional Suggestions
-
Enhance the Filter:
-
To catch more aggressive brute-force attempts, you could add a second failregex for multiple POST requests to /wp-login.php:
ini
failregex = ^<HOST> - - \[.*\] "GET /wp-login\.php\?login=failed .*"$ ^<HOST> - - \textbackslash[.*\textbackslash] "POST /wp-login\textbackslash.php .*"$- Be cautious with this, as it might increase false positives (e.g., legitimate users retrying logins). Pair it with a higher maxretry value.
-
-
Reduce False Positives:
- Adjust maxretry (e.g., to 10) or findtime (e.g., to 1200 seconds) if legitimate users are accidentally banned due to mistyped passwords.
-
Log Customization:
-
If your logs lack sufficient detail, configure your web server (e.g., Nginx or Apache) to include more information. For example, in Nginx, modify the log_format to log additional headers like X-Forwarded-For if behind a proxy:
nginx
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
-
-
Alternative Logs:
- If available, monitor WordPress-specific logs (e.g., via a security plugin like Wordfence) for more precise authentication failure data. Update the logpath and failregex accordingly.
Final Notes
This filter focuses on detecting failed login attempts via the /wp-login.php?login=failed pattern, which is practical for most WordPress setups. Depending on your Docker configuration and logging setup, you may need to tweak the logpath or failregex to match your environment. This approach provides a solid starting point for securing your WordPress Docker container with Fail2ban, balancing simplicity and effectiveness.