Skip to content

Commit 5ced365

Browse files
committed
Wordpress plugin
1 parent afea522 commit 5ced365

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

Recipes/IPBanWordpress.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
/*
3+
Plugin Name: IPBan WordPress Integration
4+
Plugin URI: https://ipban.com/
5+
Description: Sends WordPress login success and failure events to IPBan using the IPBan custom log format.
6+
Version: 1.0.0
7+
Author: DigitalRuby (IPBan)
8+
License: MIT
9+
10+
INSTRUCTIONS:
11+
- Drop this file into wp-content/plugins/IPBan/IPBanWordpress.php (create the IPBan folder if it does not exist) and activate the plugin in wp-admin.
12+
- IPBan will detect these lines automatically on Windows (C:/IPBanCustomLogs) and Linux (/var/log) using existing ipban.config entries.
13+
- On Linux, if the web server cannot write to /var/log, the plugin falls back to wp-content/plugins/IPBan/ipbancustom_wordpress.log.
14+
In that case add that fallback path to <PathAndMask> in ipban.config (e.g. /var/www/html/wp-content/plugins/IPBan/ipbancustom_wordpress.log).
15+
- Log line format examples generated:
16+
2024-10-10 12:00:00, ipban failed login, ip address: 1.2.3.4, source: WordPress, user: admin
17+
2024-10-10 12:00:10, ipban success login, ip address: 1.2.3.4, source: WordPress, user: admin
18+
*/
19+
20+
if (!defined('ABSPATH')) {
21+
exit; // Prevent direct access
22+
}
23+
24+
/**
25+
* Get remote IP address, considering possible proxy headers.
26+
*/
27+
function ipban_wp_get_remote_ip(): string {
28+
$keys = ['HTTP_CF_CONNECTING_IP', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'];
29+
foreach ($keys as $k) {
30+
if (!empty($_SERVER[$k])) {
31+
// X_FORWARDED_FOR may contain a list, take first
32+
$parts = explode(',', $_SERVER[$k]);
33+
$ip = trim($parts[0]);
34+
if ($ip !== '') {
35+
return $ip;
36+
}
37+
}
38+
}
39+
return '0.0.0.0';
40+
}
41+
42+
/**
43+
* Write a line to IPBan custom log.
44+
* @param string $type 'failed' or 'success'
45+
* @param string $username Username (may be empty for failed attempts)
46+
*/
47+
function ipban_wp_write_line(string $type, string $username): void {
48+
$ip = ipban_wp_get_remote_ip();
49+
$source = 'WordPress';
50+
$timestamp = gmdate('Y-m-d H:i:s'); // UTC
51+
$user = ($username === '' ? '-' : $username);
52+
$line = $timestamp . ', ipban ' . $type . ' login, ip address: ' . $ip . ', source: ' . $source . ', user: ' . $user . "\n";
53+
54+
if (strtoupper(PHP_OS_FAMILY) === 'WINDOWS') {
55+
$dir = 'C:/IPBanCustomLogs';
56+
if (!is_dir($dir)) { @mkdir($dir, 0777, true); }
57+
$file = $dir . '/ipban_wordpress.log';
58+
} else {
59+
// Preferred path (already monitored by ipban.config)
60+
$preferred = '/var/log/ipbancustom_wordpress.log';
61+
$preferredDir = dirname($preferred);
62+
if (@is_dir($preferredDir) && @is_writable($preferredDir)) {
63+
$file = $preferred;
64+
} else {
65+
// Fallback path inside plugin directory - requires ipban.config update
66+
$fallbackDir = WP_CONTENT_DIR . '/plugins/IPBan';
67+
if (!is_dir($fallbackDir)) { @mkdir($fallbackDir, 0777, true); }
68+
$file = $fallbackDir . '/ipbancustom_wordpress.log';
69+
}
70+
}
71+
72+
@file_put_contents($file, $line, FILE_APPEND | LOCK_EX);
73+
}
74+
75+
/**
76+
* Failed login hook.
77+
* @param string $username The attempted username.
78+
*/
79+
function ipban_wp_login_failed(string $username): void {
80+
ipban_wp_write_line('failed', $username);
81+
}
82+
add_action('wp_login_failed', 'ipban_wp_login_failed');
83+
84+
/**
85+
* Successful login hook.
86+
* @param string $user_login Username.
87+
* @param WP_User $user User object.
88+
*/
89+
function ipban_wp_login_success(string $user_login, $user): void {
90+
ipban_wp_write_line('success', $user_login);
91+
}
92+
add_action('wp_login', 'ipban_wp_login_success', 10, 2);
93+
94+
/**
95+
* Optional: Detect XML-RPC authentication failures (common brute force vector).
96+
* This simplistic approach hooks into the authentication filter; if auth returns a WP_Error we log failed.
97+
*/
98+
function ipban_wp_authenticate($user, $username) {
99+
if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) {
100+
if (is_wp_error($user)) {
101+
ipban_wp_write_line('failed', (string)$username);
102+
} elseif ($user instanceof WP_User) {
103+
ipban_wp_write_line('success', (string)$username);
104+
}
105+
}
106+
return $user;
107+
}
108+
add_filter('authenticate', 'ipban_wp_authenticate', 99, 2);
109+
110+
/**
111+
* Optional: REST API login attempts (e.g. via /wp-json/jwt-auth/v1/token). You can extend by adding specific action hooks here.
112+
*/
113+
// add_action('jwt_auth_failed', function($error){ ipban_wp_write_line('failed', '-'); });
114+
// add_action('jwt_auth_valid_token_response', function($response){ if(isset($response['user'])) ipban_wp_write_line('success', $response['user']->user_login); });
115+
116+
/* End of IPBan WordPress Integration */

0 commit comments

Comments
 (0)