=== 360 Orbit Login Guard ===
Contributors: joergliwa
Tags: security, login, brute force, limit login attempts
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 1.0.13
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Protects your login against brute-force attacks: rate limiting, login history and generic error messages, with a safety net against admin lockout.

== Description ==

Login Guard addresses the most common WordPress attack of all: automated password guessing against /wp-login.php.

* Rate limiting: locks an IP address out after too many failed attempts, for a configurable duration.
* Login history (7 days): every attempt with a pseudonymous fingerprint instead of the raw IP address, success or failure, and the user name tried (only readable if the account exists).
* Generic error messages: never reveals whether a user name exists.
* Safe allowlist behaviour: an IP address from which someone with administrator rights recently signed in successfully is only locked out after ten times the usual number of failed attempts, so a few typos never lock you out.
* Disable XML-RPC: closes the known bypass of rate limiting via system.multicall.
* Protection against user name enumeration (?author= parameter and the public REST user list).
* Export and import of all settings as JSON, to set up several sites the same way.
* WP-CLI: inspect the status and unlock IP addresses even when wp-admin itself is unreachable.

= Free version vs. Pro =

The free version is complete on its own: rate limiting, login history, generic error messages, XML-RPC and enumeration protection, and settings export/import.

**Login Guard Pro** adds:

* Two-factor authentication (TOTP) for individual accounts or entire roles, compatible with common authenticator apps.
* A custom login URL instead of /wp-login.php, with a 404 for the real address.
* Notification when an account signs in from an unknown device.
* A fixed allow/block list for IP addresses.
* Automatic update notifications directly in the WordPress admin.

Login Guard Pro is a separate plugin available from the author; it is not required to use the free version.

== Installation ==

1. Upload the plugin ZIP under *Plugins → Add New → Upload Plugin*, or install it from the plugin directory.
2. Activate the plugin.
3. Open the **Login Guard** menu and review the defaults under "Settings" (they already suit most sites).

== Frequently Asked Questions ==

= Can I lock myself out? =

This is exactly the scenario the safety net protects against: an IP address from which a person with administrator rights recently signed in successfully is only locked out after ten times the usual number of failed attempts. In addition, every lockout can be lifted with one click under "Status & Lockouts", and if wp-admin is unreachable, via WP-CLI (`wp 360-orbit-login-guard unlock <ip>`).

= Are raw IP addresses stored? =

No. The login history only stores a pseudonymous fingerprint (a hash of the IP address and a secret random value generated by the plugin). The plugin does not send any data to external services.

= What happens on deactivation? =

Rate limiting and all other protections stop immediately and the daily clean-up cron job is unscheduled. The existing login history and all settings are kept and are back immediately after reactivation. Only "Delete" in the plugin list removes them permanently.

= Which languages does the admin interface support? =

The admin interface follows the language configured in WordPress. Translations are delivered as WordPress.org language packs (translate.wordpress.org, text domain `360-orbit-login-guard`); German is maintained by the author. You are welcome to contribute further languages there.

== Screenshots ==

1. Status overview with currently locked IP addresses and the most recent login attempts.
2. Settings: rate limiting, generic error messages, proxy header handling and lockout notification.

== Changelog ==

= 1.0.13 =
* Fix: the help text in wp-admin claimed that an administrator is never locked out from an address they recently signed in from; since 1.0.12 this holds up to ten times the usual number of failed attempts.

= 1.0.12 =
* Security: "Trust the X-Forwarded-For header" now only reads the header when the request itself comes from an internal address or from a proxy you list with the `wp360_lg_trusted_proxies` filter (single addresses or ranges such as 203.0.113.0/24). Behind a CDN with public addresses, add its ranges to that filter; otherwise the header is ignored. Before, anyone who could reach the server directly could fake the header and get around the rate limit.
* Security: the exemption for a person's own address is no longer unlimited. It applies up to ten times the failed-attempt limit, so someone sharing that address can no longer guess the password without end.
* Security: an account lock now lasts at most 15 minutes and only exists for real accounts, which limits locking other people out on purpose.
* Security: "Lost your password?" counts requests for existing and non-existing accounts the same way, so the lock message no longer shows which accounts exist.
* Privacy: names that are not an account (often a password typed into the wrong field) are no longer stored in readable form in the sign-in history. A suggested privacy policy text, data export and data erasure for the history were added.
* Changed: corrected plugin logo -- lettering and symbol are now centered, the orbit is a closed ring.
* Fix: unlocking an address or account also forgets its failed attempts, so the next typo does not lock it again at once.
* Fix: successful Application Password requests are recorded at most once per hour, and expired locks are no longer listed.

= 1.0.11 =
* Fix: the German translation is now also used for Austrian, Swiss and formal German (de_AT, de_CH, de_DE_formal and so on).

= 1.0.10 =
* Fix: the one-time data migration from older versions no longer removes old settings if copying them failed, and it retries hourly until every step succeeded. A missing data table is created again. Uninstalling now also removes data left from older versions.

= 1.0.9 =
* Internal: code cleanup for the WordPress.org Plugin Check. No functional changes.

= 1.0.8 =
* Changed: all options, classes, constants and hooks now use the unique prefix wp360_ instead of we_. Existing settings and data are migrated automatically on the first page load after the update. Custom code using this plugin's filters or actions must switch to the new wp360_ names.
* Changed: the free version no longer contains any code for Pro features.
* Changed: the deactivation confirmation is now loaded through the WordPress script API instead of an inline script.

== Upgrade Notice ==



