at path:
ROOT
/
wp-content
/
plugins
/
wp-fail2ban
/
core.php
run:
R
W
Run
admin
DIR
2026-06-16 01:07:19
R
W
Run
assets
DIR
2026-06-16 01:07:19
R
W
Run
conf.d
DIR
2026-06-21 08:49:51
R
W
Run
feature
DIR
2026-06-16 01:07:19
R
W
Run
filters.d
DIR
2026-06-16 01:07:19
R
W
Run
lib
DIR
2026-06-21 08:49:51
R
W
Run
vendor
DIR
2026-06-16 01:07:19
R
W
Run
constants.php
1.06 KB
2026-06-16 01:07:19
R
W
Run
Delete
Rename
core.php
5.16 KB
2026-06-16 01:07:19
R
W
Run
Delete
Rename
freemius.php
3.32 KB
2026-06-16 01:07:19
R
W
Run
Delete
Rename
functions.php
2.39 KB
2026-06-16 01:07:19
R
W
Run
Delete
Rename
init.php
6.3 KB
2026-06-16 01:07:19
R
W
Run
Delete
Rename
readme.txt
33.1 KB
2026-06-16 01:07:19
R
W
Run
Delete
Rename
wp-fail2ban.php
1.86 KB
2026-06-16 01:07:19
R
W
Run
Delete
Rename
error_log
up
📄
core.php
Save
<?php declare(strict_types=1); /** * WP fail2ban core * * @package wp-fail2ban * @since 4.4.0 Require PHP 7.4 * @since 4.3.0 */ namespace org\lecklider\charles\wordpress\wp_fail2ban\core; use org\lecklider\charles\wordpress\wp_fail2ban\Config; use org\lecklider\charles\wordpress\wp_fail2ban\InvalidIpException; use org\lecklider\charles\wordpress\wp_fail2ban\IpRangeList; use org\lecklider\charles\wordpress\wp_fail2ban\IP; use org\lecklider\charles\wordpress\wp_fail2ban\Syslog; use function org\lecklider\charles\wordpress\wp_fail2ban\bail; defined( 'ABSPATH' ) or exit; /** * Compute remote IP address * * @since 5.0.0 * * @return IP|null * * @wp-f2b-hard Untrusted X-Forwarded-For header */ function _remote_addr(): ?IP { try { // Typical path first if ( ! defined( 'WP_FAIL2BAN_REMOTE_ADDR' ) ) { $ip = new IP( $_SERVER['REMOTE_ADDR'], true, 'REMOTE_ADDR' ); if ( array_key_exists( 'HTTP_X_FORWARDED_FOR', $_SERVER ) ) { /** * User-defined proxies, typically upstream nginx */ $proxies = new IpRangeList( Config::get( 'WP_FAIL2BAN_PROXIES' ), 'WP_FAIL2BAN_PROXIES' ); if ( 0 == count( $proxies ) ) { // No proxies set; don't care about the header return $ip; } elseif ( $proxies->containsIP( $ip ) ) { // From a known proxy $xIPs = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2 ); return new IP( $xIPs[0], true, 'HTTP_X_FORWARDED_FOR' ); } else { // Not a known proxy: hard fail and bail out Syslog::single( LOG_NOTICE, 'Untrusted X-Forwarded-For header', 'WP_FAIL2BAN_AUTH_LOG', (string) $ip ); do_action( __FUNCTION__ . '.unknown_proxy', $ip ); bail(); } } else { return $ip; } } else { /** * For plugins and themes that anonymise requests * * @since 5.0.0 Refactored * @since 3.6.0 */ return new IP( WP_FAIL2BAN_REMOTE_ADDR, true, 'WP_FAIL2BAN_REMOTE_ADDR' ); // @codeCoverageIgnore } } catch ( InvalidIpException $e ) { error_log( sprintf( "%s is invalid: '%s'", $e->getMessage(), $_SERVER['REMOTE_ADDR'] ) ); \wp_die( 'Internal server error', 'Internal server error', array( 'exit' => ! defined( 'PHPUNIT_COMPOSER_INSTALL' ), 'response' => 500, ) ); } return null; } /** * Cache results * * @since 5.0.0 Complete refactoring * * @return IP|null */ function remote_addr(): ?IP { static $remote_addr = null; if ( is_null( $remote_addr ) ) { $remote_addr = _remote_addr(); } return $remote_addr; } /** * Catch empty usernames * * @see \wp_authenticate() * * @since 4.4.0 Add type hints * @since 4.3.4.0 Refactor to use Syslog::single * @since 4.3.0 * * @param mixed|null $user * @param string $username * @param string $password * * @return mixed|null * * @wp-f2b-soft Empty username */ function authenticate( $user, string $username, string $password ) { // : ?mixed if ( empty( $username ) && isset( $_POST['log'] ) ) { Syslog::single( LOG_NOTICE, 'Empty username' ); do_action( __FUNCTION__, $user, $username, $password ); } return $user; } /** * Hook: wp_login * * @since 4.4.0 Add type hints, return type * @since 4.3.4.0 Refactor to use Syslog::single * @since 4.3.0 Add action * @since 4.1.0 Add REST support * @since 3.5.0 Refactored for unit testing * @since 1.0.0 * * @param string $user_login * @param mixed $user * * @return void * * @wp-f2b-good Accepted password for .* * * @codeCoverageIgnore */ function wp_login( string $user_login, $user ): void { Syslog::single( LOG_INFO, "Accepted password for {$user_login}" ); do_action( __FUNCTION__, $user_login, $user ); } /** * Hook: wp_login_failed * * @since 4.4.0 Add type hints, return type * @since 4.3.4.0 Refactor to use Syslog::single * @since 4.3.0.5 Handle empty username * @since 4.3.0 Add action * @since 4.2.4 Add message filter * @since 4.2.0 Change username check * @since 4.1.0 Add REST support * @since 3.5.0 Refactored for unit testing * @since 1.0.0 * * @param string $username * * @return void * * @wp-f2b-hard REST authentication attempt for unknown user .* * @wp-f2b-hard XML-RPC authentication attempt for unknown user .* * @wp-f2b-soft Authentication failure for .* * @wp-f2b-soft REST authentication failure for .* * @wp-f2b-soft XML-RPC authentication failure for .* * @wp-f2b-soft Authentication attempt for unknown user .* */ function wp_login_failed( string $username ): void { $username = trim( $username ); if ( empty( $username ) ) { $msg = 'Empty username'; $filter = '::empty'; } else { global $wp_xmlrpc_server; if ( defined( 'REST_REQUEST' ) ) { $msg = 'REST a'; $filter = '::REST'; } elseif ( $wp_xmlrpc_server ) { $msg = 'XML-RPC a'; $filter = '::XML-RPC'; } else { $msg = 'A'; $filter = ''; } $msg .= ( wp_cache_get( $username, 'useremail' ) || wp_cache_get( sanitize_user( $username ), 'userlogins' ) ) ? "uthentication failure for {$username}" : "uthentication attempt for unknown user {$username}"; } $msg = apply_filters( "wp_fail2ban::wp_login_failed{$filter}", $msg ); Syslog::single( LOG_NOTICE, $msg ); do_action( __FUNCTION__, $username ); }