Features
Brute Force Protection
Lock out IPs after repeated failed login attempts.
LoginPlus tracks failed login attempts per IP address and username together. When that pair exceeds the configured threshold within the lockout window, further attempts using that username from that IP are blocked until the window expires.
Configuration
Go to LoginPlus → Settings → Brute Force to adjust:
| Option | Default | Description |
|---|---|---|
| Enable brute force protection | On (from activation) | Toggles the feature globally |
| Max attempts | 5 | Failed logins before lockout triggers |
| Lockout duration | 15 minutes | How long the IP+username pair is blocked |
| IP allowlist | Empty | One IP per line (IPv4 or IPv6) that’s never locked out, no matter how many failures |
How it works
- Hooks the
authenticatefilter (checked before and after WordPress’s own credential check) to reject login for a locked-out IP+username pair, pluswp_login_failedto record a miss andwp_loginto reset the counter on success. - Uses WordPress transients keyed by a hash of the IP and the lowercased username — not a separate database table.
- After lockout, returns a
WP_Errorthat prevents WordPress from progressing the login. - A successful login resets the failed-attempt counter for that IP+username pair.
- The 2FA code-entry step is rate-limited the same way: if it’s ever submitted without a username (e.g. a raw HTTP replay of a captured session), attempts are bucketed by the 2FA token instead, so the 6-digit code can’t be brute-forced by skipping the username field.
Detecting the real IP behind a proxy or CDN
LoginPlus checks these in order and uses the first valid IP it finds:
CF-Connecting-IP(Cloudflare)X-Real-IPREMOTE_ADDR(the direct connecting IP)
X-Forwarded-For is deliberately not used — on a server without a properly validated reverse proxy, that header can be set by the client itself and used to spoof an IP to dodge a lockout.
Clearing a lockout manually
The lockout key includes an MD5 hash of the IP, so it can’t be typed by hand. Clear it with wp eval instead:
wp eval 'delete_transient( "lp_attempts_" . md5( "203.0.113.42" ) . "_" . strtolower( "the-username" ) );'
Replace the IP and username with the locked pair’s actual values. Alternatively, add the IP to the allowlist above if it belongs to a trusted admin or office.