
Nahnu Login Shield protects every WordPress login entry point: the login form, WooCommerce My Account, XML-RPC, the REST API and your form plugins. It is a login security plugin, not a general security suite.
No subscription. No license key. No upsell. Everything is free.
Brute-force lockout
- Attempt limit, time window and lockout duration, with escalating lockouts (default 24 h) for repeat offenders.
- Per-username lockout stops distributed botnets trying one username from many IPs.
- Honeypot usernames (admin, root, test…) lock the IP on the first attempt.
- IP blocklist and allowlist with CIDR ranges (IPv4 and IPv6), and one-click unlock.
Early blocking
An optional must-use plugin turns locked-out IPs away before WordPress loads. It is off by default and never installed automatically: click “Install early-block mu-plugin” on the General tab, and “Remove” to delete it again.
CAPTCHA / verification providers
One provider site-wide, shown on every protected form: OOPSpam (with VPN, data-centre and disposable-email blocking), reCAPTCHA v2 and v3, hCaptcha, Cloudflare Turnstile (managed or invisible), Friendly Captcha, Cap, mCaptcha and ALTCHA, or none.
Two-factor authentication
- Every user in the roles you choose gets a one-time code after their password. Email codes are always on; users can add an authenticator app (TOTP) or a passkey.
- Backup codes, admin reset for lost phones, and an emergency switch:
define( 'NAHNLS_DISABLE_2FA', true );. - Works on wp-login.php and inside WooCommerce My Account.
Passwordless sign-in
- Passkeys (WebAuthn): Touch ID, Windows Hello, phones and security keys, with browser autofill. Built-in verifier, no external service.
- Magic links: one-time email login links, hashed at rest and rate-limited, with a per-user opt-out.
White-label emails
2FA codes, magic links and signup confirmations use your sender name, logo, colours and footer. Subject, heading and intro are editable, with a preview and test send.
Access control
- Restrict roles to IP addresses or CIDR ranges.
- Login and logout redirects per role.
- XML-RPC kill switch.
- Signup email verification with pruning of unconfirmed accounts.
- Security checklist with a score and one-click fixes.
Geo-fencing
Reads the visitor country from CDN headers (Cloudflare, Bunny.net, CloudFront, Vercel, Fastly/Akamai) with no API quota, falling back to freeipapi.com or ipinfo.io with caching.
Edge blocking: Bunny.net and Cloudflare
- Push locked-out and honeypot IPs to the Bunny.net or Cloudflare WAF so attackers are stopped at the CDN edge, with automatic expiry and a block log with one-click unblock.
- Bunny Shield: one-click login rate limit (covers wp-login.php, xmlrpc.php and your custom login path), blocked IPs on a Shield access list, “Block network” for attacker ASNs, and warnings for learning mode or log-only WAF. Works with Nahnu Cache Connector for Bunny.net.
- Cloudflare WAF: one-click login rate limit on every plan (fixed limits on Free, your own on Pro and up), added next to your existing rules; blocked IPs with Unblock; “Block network” on every plan.
More protection
- JavaScript presence check blocks headless bots before CAPTCHA or lockout checks run.
- Custom login URL renames /wp-login.php; the old URL returns 404 or redirects.
- REST API: block user enumeration, apply lockouts to REST authentication, optionally disable Application Passwords.
- Sessions: idle timeout with a warning, and force-logout of all sessions.
- Notifications: login emails, admin-login alerts, new-country alerts and a weekly security digest.
WooCommerce My Account
All protections extend to the My Account login, registration, lost-password, checkout and order-tracking forms, each with its own toggle. Customers get a Login & security tab to manage passkeys, 2FA and sign-in options without seeing wp-admin. The same panel is available anywhere with the [nahnls_account_security] shortcode.
Form plugin integrations
Bricks Builder forms (per form), SureForms (all forms or the ones you pick) and the WordPress comment form, each with its own toggle. Anything else can integrate through the developer API: template tags, shortcodes, actions and filters, REST routes under nahnls/v1 and a JavaScript API (see docs/API.md).
Event log and analytics
- Search, filter by event type and date, and export to CSV. Every event shows the form or endpoint it came from.
- Daily activity, time-of-day heatmap, event breakdown, and top attacking IPs and targeted usernames.
- Configurable retention and row cap. All data stays on your site.
MainWP extension
A separate companion extension shows lockouts, edge blocks, recent events and settings across all your MainWP child sites.
Privacy
IP addresses and usernames are stored in a local database table for the event log, with configurable retention. No data is sent to any Nahnu server. Third-party services you enable receive only what they need (see below). Deleting the plugin removes all stored data.
External services
Nahnu Login Shield works fully offline by default. Each service below is contacted only when the site administrator explicitly selects or configures it in the plugin settings. No data is ever sent to a Nahnu server.
- Google reCAPTCHA (v2 / v3) — Used as the CAPTCHA provider when selected on the Widget tab. The visitor’s browser loads the widget script from
https://www.google.com/recaptcha/api.json protected forms, and Google receives the visitor’s IP address and browser information per its own policy. On every form submit the plugin sends the reCAPTCHA response token together with your reCAPTCHA secret key server-to-server tohttps://www.google.com/recaptcha/api/siteverify. Terms of Service · Privacy Policy - hCaptcha — Used as the CAPTCHA provider when selected. The visitor’s browser loads the widget from
https://js.hcaptcha.com/1/api.json protected forms (hCaptcha receives the visitor’s IP and browser data). On form submit the plugin sends the hCaptcha response token and your secret key server-to-server tohttps://api.hcaptcha.com/siteverify. Terms of Service · Privacy Policy - Cloudflare Turnstile — Used as the CAPTCHA provider when selected (managed or invisible mode). The visitor’s browser loads the widget from
https://challenges.cloudflare.com/turnstile/v0/api.json protected forms (Cloudflare receives the visitor’s IP and browser data). On form submit the plugin sends the Turnstile token and your secret key server-to-server tohttps://challenges.cloudflare.com/turnstile/v0/siteverify. Terms of Service · Privacy Policy - Friendly Captcha — Used as the CAPTCHA provider when selected. The widget script itself is bundled with the plugin (no CDN), but the visitor’s browser fetches a proof-of-work puzzle from
api.friendlycaptcha.comwhile the form is displayed (Friendly Captcha receives the visitor’s IP address). On form submit the plugin sends the solved puzzle token (frc-captcha-solution) plus your site key and your Friendly Captcha API key server-to-server tohttps://global.frcapi.com/api/v2/captcha/siteverify. Terms of Service · Privacy Policy - OOPSpam Anti-Spam — Used as the verification provider when selected; requires the separate OOPSpam Anti-Spam plugin with its own API key. On login/registration submit (and optionally at widget render) the plugin calls the OOPSpam plugin, which sends the visitor’s IP address and the submitted username/email, together with your OOPSpam API key, to the OOPSpam API to obtain a spam/VPN/data-centre score. Terms of Service · Privacy Policy
- Bunny.net API (
https://api.bunny.net) — Used only when the Bunny WAF edge-blocking integration is enabled on the Edge Blocking tab. When a lockout or honeypot event fires, the plugin sends the blocked IP address, an expiry timestamp and a short note, authenticated with your Bunny API key, to the Bunny WAF IP-block endpoint for your pull zone. The “Test connection” button reads your pull zone details with the same key. Terms of Service · Privacy Policy - Bunny Shield API (
https://api.bunny.net/shield/...) — Used only when a Bunny connection is configured on the Edge Blocking tab (your own key, or the one from the Nahnu Cache Connector for Bunny.net plugin when you choose to reuse it). The Edge Blocking tab reads your Shield zone’s plan and status, and when you click “Turn off learning mode” or “Switch the WAF to Block” it changes that one setting on your Shield zone. When you click “Create rule”, the plugin creates (and later updates or removes) one rate-limit rule containing your login paths and the limits you chose. When a lockout is pushed to Bunny and the pull zone has Shield, it creates a Shield access list with the first IP and sends it the IP addresses of locked-out visitors, removing them when the lockout expires or you unlock them. When you block a network, it sends the AS number to a second access list. All requests are authenticated with your Bunny API key. Terms of Service · Privacy Policy - Team Cymru IP-to-ASN mapping (DNS:
origin.asn.cymru.com,origin6.asn.cymru.com,asn.cymru.com) — Used only when an administrator clicks “Block network…” on a locked-out IP. The plugin makes a DNS lookup containing that IP address (reversed, as DNS requires) to find the network (AS number and name) it belongs to, and shows it for confirmation before anything is blocked. No other data is sent. Service description · Privacy Policy - Cloudflare API (
https://api.cloudflare.com/client/v4) — Used only when the Cloudflare WAF edge-blocking integration is enabled. When a lockout or honeypot event fires, the plugin creates an IP access rule containing the blocked IP address and a note, authenticated with your Cloudflare API token; a scheduled task later deletes that rule when the block expires (or when you unlock the IP), and the “Test connection” button verifies the token. On the Cloudflare WAF tab, the plugin reads the zone’s name and plan, and, only when you use them, creates, updates or deletes one rate limiting rule (the login paths and the limits) and IP access rules for the network AS numbers you block. Terms of Service · Privacy Policy - freeipapi.com — Geo-lookup fallback, used only when geo-blocking is enabled and “freeipapi” is selected as the API source and no CDN country header is present. On a login attempt the plugin sends the visitor’s IP address (and your optional API key as a bearer token) to
https://free.freeipapi.com/api/json/{ip}to learn its country code; results are cached locally per IP. Terms of Use · Privacy Policy - ipinfo.io — Geo-lookup fallback, used only when geo-blocking is enabled and “ipinfo” is selected as the API source. On a login attempt the plugin sends the visitor’s IP address (and your optional API token) to
https://api.ipinfo.io/lite/{ip}to learn its country code; results are cached locally per IP. Terms of Service · Privacy Policy - Self-hosted Cap and mCaptcha instances — If you select the Cap or mCaptcha provider you must enter the URL of an instance you host. The visitor’s browser loads that instance’s widget script, and on form submit the plugin sends the challenge token and your secret key server-to-server to
{your-instance}/siteverify(Cap) or{your-instance}/api/v1/pow/siteverify(mCaptcha). No third party is involved unless you point the URL at one; see the Cap and mCaptcha documentation for their respective terms. - ALTCHA — If selected, verification is handled locally by the separately installed ALTCHA plugin; this plugin makes no external request for it.
Country flags shown in the admin log are SVG files bundled with the plugin (assets/img/flags/); no flag CDN or other external image service is used.
Bundled third-party libraries
No scripts are loaded from a CDN. These libraries ship inside the plugin (assets/vendor/ unless noted otherwise):
- Chart.js 4.4.1 — MIT License, https://www.chartjs.org. Used on the Analytics admin tab.
- Friendly Captcha widget (friendly-challenge 0.9.18) — MIT License, https://github.com/FriendlyCaptcha/friendly-challenge. Used only when Friendly Captcha is the selected CAPTCHA provider.
- flag-icons (country flag SVGs in assets/img/flags/) — MIT License, https://github.com/lipis/flag-icons. Displayed in the admin event log; loaded from the plugin folder, never from a CDN.
Screenshots

General tab — today's stats, the master switch, which forms to protect, the dashboard widget, the optional early-block mu-plugin and the JavaScript check.

Widget tab — pick the CAPTCHA provider (OOPSpam, reCAPTCHA v2/v3, hCaptcha, Turnstile, Friendly Captcha) with a live preview.

Geo tab — block the login form by country using CDN geo headers or an IP lookup API.

Edge Blocking tab, IP Blocking — push lockouts and honeypot hits to the Bunny.net or Cloudflare WAF so attackers are stopped at the edge.

Lockout tab — failed-attempt thresholds, escalation to long bans, the lockout message and proxy header settings.

Integrations tab — WooCommerce My Account forms plus Bricks Builder, SureForms and WordPress comment protection.

2FA tab — two-factor authentication for selected roles, with email codes as the baseline and authenticator apps or passkeys as stronger options.

Passwordless tab — magic login links and passkeys (WebAuthn).

Settings tab — log retention and white-label email branding for every email the plugin sends.