Skip to content
Developry Plugins
  • Plugins
  • About
  • Contact
  • Categories
    • Advanced Custom Fields (ACF) Tutorials
    • Backup & Disaster Recovery
    • Block Editor & Gutenberg Tutorials
    • WordPress Development
    • WordPress Performance & Speed
    • WordPress Plugin Development Guide
    • WordPress Security & Protection
    • WordPress SEO & Digital Marketing
    • WordPress Theme Development
    • WordPress Tips Tricks & Hacks
  • Blog
GitHub
Home / WordPress Security & Protection / How to Block Brute Force Attacks on WordPress Login Pages

How to Block Brute Force Attacks on WordPress Login Pages

August 10, 2026 By Krasen Slavov WordPress Security & Protection

Brute force attacks on WordPress login pages are relentless. Bots try thousands of username/password combinations until they gain access. These attacks consume server resources, slow down your site, and eventually succeed against weak passwords.

This guide provides multiple defensive layers to block brute force attacks, from limiting login attempts to IP whitelisting and CAPTCHA implementation.

Understanding Brute Force Attacks

How They Work

Attackers use automated scripts to try common passwords against wp-login.php:

admin / password
admin / 123456
admin / admin123
administrator / password
...thousands more combinations

Signs of an Attack

  • Hundreds of failed login attempts in logs
  • Increased server CPU/memory usage
  • Slow admin dashboard
  • Email flood of failed login notifications
  • IP addresses from foreign countries
  • Automated bot patterns (rapid-fire attempts)

Layer 1: Limit Login Attempts

Using Limit Login Attempts Reloaded

# Install via WP-CLI
wp plugin install limit-login-attempts-reloaded --activate

Recommended Settings:

  • Allowed attempts: 4
  • Lockout duration: 20 minutes
  • Reset after: 12 hours
  • Long lockout: 24 hours after 4 lockouts

Manual Implementation:

// In functions.php or custom plugin
add_action('wp_login_failed', 'track_failed_login');

function track_failed_login($username) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $attempts = get_transient('failed_login_' . $ip) ?: 0;
    $attempts++;

    set_transient('failed_login_' . $ip, $attempts, 20 * MINUTE_IN_SECONDS);

    if ($attempts >= 5) {
        // Lock out this IP
        set_transient('lockout_' . $ip, true, HOUR_IN_SECONDS);
        wp_die('Too many failed login attempts. Please try again in 1 hour.');
    }
}

// Check before allowing login
add_filter('authenticate', 'check_lockout', 30, 3);

function check_lockout($user, $username, $password) {
    $ip = $_SERVER['REMOTE_ADDR'];

    if (get_transient('lockout_' . $ip)) {
        return new WP_Error('lockout', 'Account locked due to too many failed attempts.');
    }

    return $user;
}

Layer 2: Add CAPTCHA Protection

Google reCAPTCHA v3 Integration

// Add to functions.php

// Enqueue reCAPTCHA script
add_action('login_enqueue_scripts', 'add_recaptcha_to_login');

function add_recaptcha_to_login() {
    ?>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    <script>
    function onSubmit(token) {
        document.getElementById("loginform").submit();
    }
    </script>
    <?php
}

// Add reCAPTCHA to login form
add_action('login_form', 'display_recaptcha');

function display_recaptcha() {
    ?>
    <div class="g-recaptcha" data-sitekey="YOUR_SITE_KEY" data-callback="onSubmit"></div>
    <?php
}

// Verify reCAPTCHA
add_filter('authenticate', 'verify_recaptcha', 30, 3);

function verify_recaptcha($user, $username, $password) {
    if (empty($_POST['g-recaptcha-response'])) {
        return new WP_Error('captcha_failed', 'Please complete the reCAPTCHA.');
    }

    $recaptcha = $_POST['g-recaptcha-response'];
    $secret_key = 'YOUR_SECRET_KEY';

    $response = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', [
        'body' => [
            'secret' => $secret_key,
            'response' => $recaptcha,
            'remoteip' => $_SERVER['REMOTE_ADDR']
        ]
    ]);

    $response_body = json_decode(wp_remote_retrieve_body($response));

    if (!$response_body->success || $response_body->score < 0.5) {
        return new WP_Error('captcha_failed', 'reCAPTCHA verification failed.');
    }

    return $user;
}

Layer 3: Change Login URL

Using WPS Hide Login Plugin

wp plugin install wps-hide-login --activate

Settings: Change /wp-login.php to /my-secure-login

Manual Method (via .htaccess):

# Redirect wp-login.php to custom URL
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/wp-login\.php
RewriteCond %{QUERY_STRING} !^action=logout
RewriteCond %{QUERY_STRING} !^action=rp
RewriteCond %{QUERY_STRING} !^action=register
RewriteRule ^(.*)$ /custom-login-url? [R=301,L]

Caution: Remember your custom URL. Losing it locks you out.

Layer 4: IP Whitelisting

Restrict wp-admin by IP

# In wp-admin/.htaccess
<Files admin-ajax.php>
    Order allow,deny
    Allow from all
    Satisfy any
</Files>

# Block all other wp-admin access except your IP
Order deny,allow
Deny from all
Allow from 123.456.789.0
Allow from 987.654.321.0

For Nginx:

location ~* /wp-admin/ {
    allow 123.456.789.0;
    deny all;
}

Dynamic IP Solution (for VPN/mobile users):

// In functions.php - Email-based IP whitelisting
add_action('wp_login_failed', 'email_whitelist_request');

function email_whitelist_request($username) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $whitelist = get_option('ip_whitelist', []);

    if (!in_array($ip, $whitelist)) {
        // Send email to admin with "approve" link
        $approve_url = admin_url('admin.php?action=approve_ip&ip=' . $ip);
        wp_mail(
            get_option('admin_email'),
            'New IP Login Attempt',
            "Approve IP $ip: $approve_url"
        );
    }
}

Layer 5: WordPress Firewall

Wordfence Configuration

wp plugin install wordfence --activate

Essential Settings:

  1. Enable Extended Protection (premium feature)

  2. Brute Force Protection:

    • Enable login page CAPTCHA
    • Immediately block invalid usernames
    • Lock out after 5 failed logins
  3. Advanced Blocking:

    • Block attackers from specific countries
    • Throttle login attempts
    • Block known malicious IPs

Rate Limiting Example:

// Wordfence alternative - manual rate limiting
add_action('login_form', 'add_login_delay');

function add_login_delay() {
    $ip = $_SERVER['REMOTE_ADDR'];
    $last_attempt = get_transient('last_login_attempt_' . $ip);

    if ($last_attempt && (time() - $last_attempt) < 3) {
        sleep(3); // Force 3-second delay between attempts
    }

    set_transient('last_login_attempt_' . $ip, time(), MINUTE_IN_SECONDS);
}

Layer 6: Cloudflare Protection

Enable Cloudflare Firewall Rules

  1. Sign up for Cloudflare (free plan works)
  2. Add your domain
  3. Update nameservers
  4. Enable “Under Attack Mode” during active brute force

Firewall Rule:

(http.request.uri.path contains "/wp-login.php") and
(not ip.geoip.country in {"US" "CA" "GB"})

This blocks non-US/CA/GB traffic to login page.

Layer 7: Two-Factor Authentication

Combine 2FA with login limits for ultimate protection:

wp plugin install two-factor --activate

Even if attackers guess passwords, they can’t login without the second factor.

Layer 8: Disable XML-RPC

XML-RPC can be used for brute force attacks:

# In .htaccess
<Files xmlrpc.php>
    Order deny,allow
    Deny from all
</Files>

Or via plugin code:

// Completely disable XML-RPC
add_filter('xmlrpc_enabled', '__return_false');

// Or disable only certain methods
add_filter('xmlrpc_methods', 'disable_xmlrpc_methods');

function disable_xmlrpc_methods($methods) {
    unset($methods['wp.getUsersBlogs']);
    unset($methods['system.multicall']);
    unset($methods['system.listMethods']);
    return $methods;
}

Layer 9: Server-Level Protection (Fail2Ban)

Configure Fail2Ban for WordPress

# Install Fail2Ban (Ubuntu/Debian)
sudo apt-get install fail2ban

# Create WordPress filter
sudo nano /etc/fail2ban/filter.d/wordpress.conf

Filter Content:

[Definition]
failregex = ^<HOST> .* "POST /wp-login.php
            ^<HOST> .* "POST /xmlrpc.php
ignoreregex =

Jail Configuration:

# In /etc/fail2ban/jail.local
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/apache2/access.log
maxretry = 5
bantime = 3600
findtime = 600

Restart Fail2Ban:

sudo systemctl restart fail2ban

Monitoring and Alerts

Email Notifications

// Email admin on failed logins
add_action('wp_login_failed', 'notify_failed_login');

function notify_failed_login($username) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $time = current_time('mysql');

    wp_mail(
        get_option('admin_email'),
        'Failed Login Attempt',
        "Failed login for username: $username\nIP: $ip\nTime: $time"
    );
}

Log Analysis

# View recent failed logins (Apache)
grep "wp-login.php" /var/log/apache2/access.log | grep "POST" | tail -50

# Count attempts by IP
awk '{print $1}' /var/log/apache2/access.log | grep -v "^$" | sort | uniq -c | sort -rn | head -20

Testing Your Protection

Safe Simulation

  1. Use incognito browser
  2. Attempt 5-6 failed logins
  3. Verify lockout occurs
  4. Check email notifications
  5. Confirm CAPTCHA appears (if configured)
  6. Test IP whitelist (from different IP)

Automated Test:

# Test with curl (safely)
for i in {1..6}; do
    curl -X POST https://yoursite.com/wp-login.php \
    -d "log=testuser&pwd=wrongpassword"
    sleep 2
done

Best Practices Summary

✅ Do:

  • Limit login attempts (4-5 max)
  • Add CAPTCHA protection
  • Use strong, unique passwords
  • Enable 2FA for all admins
  • Monitor failed login logs
  • Update security plugins regularly

❌ Don’t:

  • Use “admin” as username
  • Allow unlimited login attempts
  • Ignore failed login notifications
  • Use same password across accounts
  • Disable security features for convenience

Complete Protection Stack

Recommended combination:

  1. Strong passwords (20+ characters)
  2. Limit Login Attempts Reloaded (free)
  3. Google reCAPTCHA v3 (free)
  4. Wordfence or Sucuri (free/premium)
  5. Two-Factor Authentication (free)
  6. Cloudflare (free tier sufficient)
  7. Fail2Ban (server-level, free)

This multi-layered approach stops 99.9% of brute force attacks while maintaining usability for legitimate users.

Brute force attacks are preventable. By implementing these protective layers, you transform WordPress login from a vulnerable entry point into a hardened fortress. Start with basic login limits and CAPTCHA, then add additional layers based on your threat level and resources.

External Links

  1. Limit Login Attempts Reloaded
  2. Google reCAPTCHA
  3. Wordfence Security
  4. Cloudflare
  5. Fail2Ban

Call to Action

Secure your site with bulletproof backups! Backup Copilot Pro offers automated security audits, malware scanning before backups, and instant recovery—try it free!

Tags:
brute force protection firewall limit login attempts login security wordpress security
Share:
Previous Post How to Build Dynamic Blocks with WordPress Block Editor
Next Post How to Add Custom User Roles and Capabilities in WordPress

Related Articles

December 30, 2025

WordPress Security Checklist: 50 Steps to Harden Your Website

WordPress security isn’t optional—it’s essential. With over 40% of the web running...
July 10, 2026

How to Fix Hacked WordPress Site: Complete Recovery Guide

Discovering your WordPress site has been hacked is a nightmare scenario. Your...
December 25, 2025

WordPress Security Plugins Comparison: Which Is Best in 2025?

Choosing the right security plugin can mean the difference between a protected...
  • Privacy Policy
  • Terms of Use
  • Documentation
  • FAQs
  • Contact

© 2026 Developry Plugins. All rights reserved.

GitHub Twitter/X

Search

Popular Searches

  • Plugins
  • Tutorials
  • Documentation