Limiting the Number of Login Attempts in WordPress

First, I noticed on my websites, then read several tweets on Twitter that there are mass brute force attacks on WordPress blogs: Chinese bots are trying passwords by sending POST requests to the file wp-login.php.

The problem is not that the site can be hacked, as there are plugins to limit the number of login attempts: Limit Login Attempts, but that the WordPress engine is "heavy" and such requests create excessive load on the server. This happens because the plugin requires the WordPress environment, the file wp-load.php, and when it is loaded, many calculations are made before the plugin starts working. Add about 20 requests per second here and you will understand how difficult it is for the server...

Kama WP Limit Login

My hosting started complaining about excessive loads. I needed protection, so I wrote a small PHP script, naming it "kama_wp_limit_login". It limits login attempts to 3 within an hour. The beauty of it is that the code works outside of WordPress: first, the IP and the last "login" time are checked, if everything is OK, then WordPress works as usual, if not - the PHP work is interrupted before reaching WordPress and a message is displayed.

Installing Kama WP Limit Login

  1. Clone the git repository into your project:

    $ git clone [email protected]:doiftrue/wp_limit_login.git

    Or download this archive:

    Download: V4
    Downloaded: 28, size: 0
  2. Upload the folder from the archive wp_limit_login to the root of your site, where wp-config.php is located.

  3. Set the permissions to 755 for the cache folder, so that the server can create and modify files in this folder. On some servers, such permissions are set by default.

  4. Open the file wp-config.php and at the very beginning, after <?php, insert this line:

    require __DIR__ . '/wp_limit_login/main.php';
  5. Done!
Checking

To make sure everything is working, you need to incorrectly log in 3 times. After 3 attempts, you should see a blocking message.

A Little Poetry

This is not a WordPress plugin and therefore the script is connected unusually.

-

If you have several sites on one host, you can find the parent directory for all sites and place the wp_limit_login folder there. And for each site in wp-config.php, specify similar code, instead of the one given above:

require dirname( __DIR__, 2 ) . '/wp_limit_login/main.php';

where 2 means that the wp_limit_login folder is located 2 directories above, in the files wp-config.php of your sites.

Protecting/Blocking the Site Using .htaccess + .htpasswd

Another protection option is to set a password on the server to access the wp-login.php file.

The principle of operation is that when accessing the wp-login.php page, the user will be shown an additional authentication window where they need to enter a password to access wp-login.php (the appearance of the window depends on the browser).

login-w

If the password is entered correctly, the server allows access to the file, and then you can log in to WordPress as usual.

Steps:

Step 1: Create the .htpasswd file

In the root of your site, create a file specifying the login and password for access. You can specify multiple logins and passwords for different users:

kama:$apr1$Q9Gnetdv$pZyL9sGbN3ynC4k2oAZaQ.
andreas:$apr1$dHjB0/..$mkTTbqwpK/0h/rz4ZeN8M0
john:$apr1$IHaD0/..$N9ne/Bqnh8.MyOtvKU56j1

You can enter as many users as you want. Use special services to generate such strings, for example, this one.

Step 2: Include the .htpasswd file

Open the .htaccess file, which should be next to the .htpasswd file just created, and add the following code to it (anywhere):

<Files wp-login.php>
AuthName "Access Denied"
AuthType Basic
AuthUserFile /home/www/example.com/.htpasswd
require valid-user
</Files>

Don't forget to change the path to the file to /home/www/example.com

Done! Now try to log in to WordPress. You will see an additional window for entering the login and password. This protection will shield you from brute force attacks.

Nginx

You can also set up blocking at the Nginx level. To do this, you can use the following directives in the domain's configuration file:

  • auth_basic string | off;
  • auth_basic_user_file file;

Read more about the directives here.

Example of using directives:

server {
	listen 443 ssl http2;
	server_name example.com;

	# other directives...

	location / {
		auth_basic "Restricted Access!";
		auth_basic_user_file /etc/nginx/htpasswd_example.com;

		index index.php;
		try_files $uri $uri/ /index.php?$args;
	}

	# other directives...
}

Now in the file /etc/nginx/htpasswd_example.com, you need to specify the passwords. The file format is as follows:

# comment
name1:password1
name2:password2:comment
kama:$wet1$F4HT89kL$f0gEMNpFKZNH4VggDMYTm0

This example will password-protect the site for all requests to the site (except for static files).