How to Block access to wp-admin for all external countries

Days ago I was thinking about how could I increase the security of my wp-admin area and wp-login.php file from my WordPress installations. That’s when I started investigating until I found a good way to do it. On this post I will show you a simple way to block access to wp-admin for external countries, and allow only your own local country.

This uses the same principle as for restricting FTP & cPanel ports connections from allowed countries only, but instead of using CSF Firewall rules to load the ip ranges from each country, we are using just an allow/deny configuration from our web server, same as we did posts ago when we explained how to block URL access to wp-admin and wp-login.php to all except my IP address on Nginx

Block access to wp-admin for external countries using allow/deny rules

In order to block access to wp-admin area, you first need to grab the ip range address from your local country. For this we will use database from several sites like IPDeny or CIPRG, download the file zone containing all your local IP addresses ranges.

In my case, as I use Nginx web server I saved the IP ranges on this location:

/etc/nginx/conf.d/security/uruguay-allow.conf

This file contains all the IP addresses and ranges from my local country (Uruguay), for example:

[[email protected]:~]more /etc/nginx/conf.d/security/uruguay-allow.conf
allow 23.205.124.0/23;
allow 23.208.176.0/20;
allow 23.208.192.0/20;
allow 23.208.208.0/22;
allow 57.75.80.0/20;
allow 57.75.224.0/20;
allow 65.48.26.168/29;
allow 65.110.34.20/30;

Then add a simple allow/deny block on Nginx: this is using an include with all the allowed IP ranges, it’s simpler than including all on the same vhost configuration.

	# wp-admin block to all countries	
	location ~ ^/(wp-admin|wp-login\.php) {
	        include /etc/nginx/conf.d/security/uruguay-allow.conf;
                deny all;
	
		# PHP-Parsing with PHP-FPM
	        location ~ \.php$ {
        	    try_files $uri =404;
	            fastcgi_pass   unix:/tmp/nixcp_php5-fpm.sock;
        	    fastcgi_index  index.php;
	            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
	            include        fastcgi_params;
	            fastcgi_buffer_size 128k;
	            fastcgi_buffers 256 4k;
        	    fastcgi_busy_buffers_size 256k;
	            fastcgi_temp_file_write_size 256k;
	       }
	}

For Apache or LiteSpeed you can use .htaccess:

You can place a simple allow deny as you see below:

<FilesMatch wp-login.php>

order deny,allow
Deny from all

# whitelist your IPs here
allow from xx.xxx.xx.xx
allow from xx.xxx.xx.xx

</FilesMatch>

Apache is way different than Nginx. On apache .htaccess files you can’t include rules, definitions, directives or statements from other external files. The Include directive can’t be used inside an htaccess file, that’s why you will have to include all the IP ranges on the .htaccess file, that can lead to a very large file, be aware of that.

Downside of this method

If you choose to block access to wp-admin for external countries using the previous method you will notice it is not dynamic at all, you will have to download and update your ranges from time to time. A good way to automate this is to write a simple bash or perl script to download the ip address range zone file, remove the unwanted characters and replace the old file on your server.

Due to the large number of lines that can fit into the .htaccess files it is not really a performance focused solution, but it may work for small countries where you don’t have too much internet assigned ranges, as happened in my case.

And as Clayton commented below:

Getting thousands of rules into an iptables style list can cause huge connection lag on all web services for the account. It has to check every ip connecting against EVERY item in your lists, as you can imagine as the lists get longer, so does it deciding on whether or not to let a user connect.

This solution may work perfectly if you apply to few accounts, not massive on all your users, and always using small country ranges.

Conclusion

As you can see, this method is useful if you have local traffic only, and if you have a dedicated or vps server.

Unless you work with Nginx, which doesn’t read and scan .htaccess files as Apache, it will be hard to apply this method to Apache or LiteSpeed on a very big number of files.

I’m still trying to find a server side solution that runs natively on Nginx and Apache, or on the network side with some custom rule from CSF Firewall. If you know how to do it using a firewall rule, it will be really usefull for all of us, please share your knowedge with us.

If you need a more generic way to block brute force attacks on WordPress, you can check out our Comodo WAF installation for cPanel guide, which includes rules to block wordpress brute force attacks.

 

About the Author: Esteban Borges

Experienced Sr. Linux SysAdmin and Web Technologist, passionate about building tools, automating processes, fixing server issues, troubleshooting, securing and optimizing high traffic websites.

2 Comments

  1. This is a HUGE no no. Getting thousands of rules into an iptables style list will cause HUGE connection lag on all web services for the account. It has to check every ip connecting against EVERY item in your lists, as you can imagine as the lists get longer, so does it deciding on whether or not to let a user connect.

    1. Hey Clayton.

      It may not be the best solution for massive users, I agree, in fact I already stated that before on the post:

      “Due to the large number of lines that can fit into the .htaccess files it is not really a performance focused solution, but it may work for small countries where you don’t have too much internet assigned ranges.”

      I’ve now edited the post to include your warning also if used with large ranges or massively with lot of users.

      Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *