PHPwordpressadvanced

WordPress Limit Login Attempts

Add brute force protection by limiting failed login attempts

#wordpress#security#login#brute-force#protection
Share this snippet:

Code

php
1// Limit login attempts
2function limit_login_attempts() {
3 // Get IP address
4 $ip = $_SERVER['REMOTE_ADDR'];
5
6 // Get transient
7 $attempts = get_transient('login_attempts_' . $ip);
8
9 if ($attempts === false) {
10 $attempts = 0;
11 }
12
13 return $attempts;
14}
15
16// Check if IP is blocked
17function is_ip_blocked() {
18 $ip = $_SERVER['REMOTE_ADDR'];
19 $blocked = get_transient('login_blocked_' . $ip);
20
21 return $blocked !== false;
22}
23
24// Authenticate filter
25function check_login_attempts($user, $username, $password) {
26 // Check if IP is blocked
27 if (is_ip_blocked()) {
28 $minutes = 30; // Block duration
29 return new WP_Error(
30 'too_many_attempts',
31 sprintf(
32 __('Too many failed login attempts. Please try again in %d minutes.'),
33 $minutes
34 )
35 );
36 }
37
38 return $user;
39}
40add_filter('authenticate', 'check_login_attempts', 30, 3);
41
42// Track failed logins
43function track_failed_login($username) {
44 $ip = $_SERVER['REMOTE_ADDR'];
45 $max_attempts = 5; // Maximum attempts allowed
46 $lockout_duration = 30 * 60; // 30 minutes in seconds
47
48 // Get current attempts
49 $attempts = limit_login_attempts();
50 $attempts++;
51
52 // Set transient for 1 hour
53 set_transient('login_attempts_' . $ip, $attempts, 3600);
54
55 // Block IP if max attempts reached
56 if ($attempts >= $max_attempts) {
57 set_transient('login_blocked_' . $ip, true, $lockout_duration);
58
59 // Log the event
60 error_log(sprintf(
61 'IP %s blocked after %d failed login attempts for user: %s',
62 $ip,
63 $attempts,
64 $username
65 ));
66
67 // Optional: Send email notification
68 $admin_email = get_option('admin_email');
69 $subject = 'Security Alert: Login Attempts Blocked';
70 $message = sprintf(
71 "IP Address: %s\nUsername: %s\nAttempts: %d\nTime: %s",
72 $ip,
73 $username,
74 $attempts,
75 current_time('mysql')
76 );
77
78 wp_mail($admin_email, $subject, $message);
79 }
80}
81add_action('wp_login_failed', 'track_failed_login');
82
83// Reset attempts on successful login
84function reset_login_attempts($user_login, $user) {
85 $ip = $_SERVER['REMOTE_ADDR'];
86 delete_transient('login_attempts_' . $ip);
87 delete_transient('login_blocked_' . $ip);
88}
89add_action('wp_login', 'reset_login_attempts', 10, 2);
90
91// Add custom error message
92function custom_login_error_message($errors) {
93 if (is_ip_blocked()) {
94 $errors = new WP_Error();
95 $errors->add(
96 'blocked',
97 __('<strong>ERROR</strong>: Too many failed login attempts. Your IP has been temporarily blocked.')
98 );
99 }
100
101 return $errors;
102}
103add_filter('wp_login_errors', 'custom_login_error_message');

WordPress Limit Login Attempts

Protect your WordPress site from brute force attacks by limiting the number of failed login attempts from a single IP address.

// Limit login attempts
function limit_login_attempts() {
    // Get IP address
    $ip = $_SERVER['REMOTE_ADDR'];

    // Get transient
    $attempts = get_transient('login_attempts_' . $ip);

    if ($attempts === false) {
        $attempts = 0;
    }

    return $attempts;
}

// Check if IP is blocked
function is_ip_blocked() {
    $ip = $_SERVER['REMOTE_ADDR'];
    $blocked = get_transient('login_blocked_' . $ip);

    return $blocked !== false;
}

// Authenticate filter
function check_login_attempts($user, $username, $password) {
    // Check if IP is blocked
    if (is_ip_blocked()) {
        $minutes = 30; // Block duration
        return new WP_Error(
            'too_many_attempts',
            sprintf(
                __('Too many failed login attempts. Please try again in %d minutes.'),
                $minutes
            )
        );
    }

    return $user;
}
add_filter('authenticate', 'check_login_attempts', 30, 3);

// Track failed logins
function track_failed_login($username) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $max_attempts = 5; // Maximum attempts allowed
    $lockout_duration = 30 * 60; // 30 minutes in seconds

    // Get current attempts
    $attempts = limit_login_attempts();
    $attempts++;

    // Set transient for 1 hour
    set_transient('login_attempts_' . $ip, $attempts, 3600);

    // Block IP if max attempts reached
    if ($attempts >= $max_attempts) {
        set_transient('login_blocked_' . $ip, true, $lockout_duration);

        // Log the event
        error_log(sprintf(
            'IP %s blocked after %d failed login attempts for user: %s',
            $ip,
            $attempts,
            $username
        ));

        // Optional: Send email notification
        $admin_email = get_option('admin_email');
        $subject = 'Security Alert: Login Attempts Blocked';
        $message = sprintf(
            "IP Address: %s\nUsername: %s\nAttempts: %d\nTime: %s",
            $ip,
            $username,
            $attempts,
            current_time('mysql')
        );

        wp_mail($admin_email, $subject, $message);
    }
}
add_action('wp_login_failed', 'track_failed_login');

// Reset attempts on successful login
function reset_login_attempts($user_login, $user) {
    $ip = $_SERVER['REMOTE_ADDR'];
    delete_transient('login_attempts_' . $ip);
    delete_transient('login_blocked_' . $ip);
}
add_action('wp_login', 'reset_login_attempts', 10, 2);

// Add custom error message
function custom_login_error_message($errors) {
    if (is_ip_blocked()) {
        $errors = new WP_Error();
        $errors->add(
            'blocked',
            __('<strong>ERROR</strong>: Too many failed login attempts. Your IP has been temporarily blocked.')
        );
    }

    return $errors;
}
add_filter('wp_login_errors', 'custom_login_error_message');

Admin Notification Function

// Get blocked IPs count
function get_blocked_ips_count() {
    global $wpdb;

    $query = "SELECT COUNT(*) FROM {$wpdb->options}
              WHERE option_name LIKE '_transient_login_blocked_%'";

    return $wpdb->get_var($query);
}

// Display admin notice
function login_attempts_admin_notice() {
    $blocked_count = get_blocked_ips_count();

    if ($blocked_count > 0) {
        echo '<div class="notice notice-warning is-dismissible">';
        echo '<p><strong>Security Notice:</strong> ' . $blocked_count . ' IP address(es) currently blocked due to failed login attempts.</p>';
        echo '</div>';
    }
}
add_action('admin_notices', 'login_attempts_admin_notice');

Advanced: Whitelist IPs

// Whitelist specific IPs
function is_ip_whitelisted() {
    $ip = $_SERVER['REMOTE_ADDR'];

    $whitelist = array(
        '192.168.1.1',
        '10.0.0.1',
        // Add your IPs here
    );

    return in_array($ip, $whitelist);
}

// Modified authenticate check with whitelist
function check_login_attempts_with_whitelist($user, $username, $password) {
    // Skip check for whitelisted IPs
    if (is_ip_whitelisted()) {
        return $user;
    }

    if (is_ip_blocked()) {
        return new WP_Error(
            'too_many_attempts',
            __('Too many failed login attempts. Please try again later.')
        );
    }

    return $user;
}
add_filter('authenticate', 'check_login_attempts_with_whitelist', 30, 3);

Configuration Options

// Customizable settings
define('LOGIN_MAX_ATTEMPTS', 5);           // Maximum failed attempts
define('LOGIN_LOCKOUT_DURATION', 1800);    // Lockout time in seconds (30 min)
define('LOGIN_ATTEMPTS_WINDOW', 3600);     // Time window for attempts (1 hour)

Features

  • Brute Force Protection: Limits failed login attempts
  • IP Blocking: Temporarily blocks suspicious IPs
  • Email Notifications: Alerts admins of security events
  • Whitelist Support: Bypass protection for trusted IPs
  • Customizable: Adjust attempt limits and durations
  • Logging: Track failed attempts for security auditing

Related Snippets