This article describes briefly how to secure your WordPress website when using Linux, Apache V2.4 and PHP 7 FPM.
It explains how you can restrict by IP Address (or whitelist specific IP addresses for) the critical administration and configuration pages and scripts of the WordPress Administration. The idea is that only you and your team can access those pages, and not foreigners such as hacker bots.
Apache V2.4.x is the latest mainstream Apache version.
PHP 7 FPM is a PHP FastCGI Process Manager implementation. PHP-FPM is the preferred setup when serving PHP via the Apache and Nginx web server. It is part of the core of PHP 7.x. The idea is that the Apache process proxies incoming HTTP Requests to PHP FPM using the FastCGI mechanism. The important part here is that the Apache Server no longer retrieves the PHP script from the file system but delegates it to the daemon PHP-FPM (this last aspect is important as you will see later in this article).
The deprecated and bad-for-performance setup of running PHP scripts on a Apache web server is by using the Apache module called “PHP”. This means the the PHP scripts are retrieved from the file system, and executed, within the Apache system.
Have you also followed some tutorials (Google wordpress+php-login.php+apache+require+denied) which describe how to secure your WordPress website?
And have you also experienced that some parts of these tutorials work, and some parts do not…
First make sure that you ignore the tutorials that are about the old V2.2 version of Apache. They use the deprecated directives
Order Deny,Allow and
Deny from all and
Allow from xxx.xxx.xxx.xxx. The official WordPress brute force attacks page is one of them…
Now let me give you a typical example for Apache V2.4:
1. Create/modify the .htaccess file in your main WordPress directory /webroot
#CODE <Files "wp-config.php"> Require all denied </Files> <Files "xmlrpc.php"> Require all denied </Files> <Files "wp-login.php"> # Allow only my team's IP addresses Require ip 18.104.22.168 22.214.171.124 </Files>
2. Create/modify the .htaccess file in your WordPress directory /wp-admin/
#CODE # Allow only my team's IP addresses Require ip 126.96.36.199 188.8.131.52
Do you see what the problem is? Test it and see for yourself.
The directive for the directory /wp-admin/ works fine.
But the <Files> directives for the files in /webroot do not seem to work. In other words, access to /wp-login.php is wide open so any bot can starting guessing passwords in a loop; it might not guess your very secure password but it puts an unneccessary load on the system because each time it executes a PHP script.
Tip: you can enable extra logging in your virtual host config and check that yourself in the error log.
#CONFIG LogLevel info authz_core:trace8 rewrite:trace8
#ERROR LOG [authz_core:debug] [pid 11369:tid 140416280119040] mod_authz_core.c(835): [client 184.108.40.206.:50166] AH01628: authorization result: granted (no directives)
The root cause is that, for our configuration Apache + PHP FPM, the Apache server actually does not retrieve the PHP script(s) from the file system (the PHP FPM daemon/processes do so) and so it cannot apply the
A BETTER WAY TO CONFIGURE THIS
Allow me to propose a correct way to configure this.
The .htaccess file in your WordPress directory /wp-admin/ can remain because it is working fine.
The idea for the other restrictions is to use the <Location> directives of Apache, These directives act upon the URL of the incoming HTTP request (opposed to acting upon files on the file system using
The directives in the .htaccess file in your main WordPress directory /webroot must be removed.
1. Create an Apache include file, e.g.
#CODE ## Apache: vhost include: WordPress security ## @seq after the
entry in the vhost config file. ## @info This config file is only to be used by me in virtual hosts definitions, the config file in ./conf-available/ IS NOT LINKED TO ./conf-enabled/ <LocationMatch "(?i:\/wp-config\.php)"> Require all denied </LocationMatch> <LocationMatch "(?i:\/xmlrpc\.php)"> Require all denied </LocationMatch> <LocationMatch "(?i:\/wp-login\.php)"> Require all denied Require ip 220.127.116.11 18.104.22.168 </LocationMatch>
2. Use the include file in the virtual host config file for your website(s) e.g.
/etc/apache2/sites-available/www-foo-com-be-80.conf. Put it after the
#CODE ## ## Apache: vhost include: WordPress security ## include /etc/apache2/conf-available/my_wordpress_security__vhost_include.conf
That is all folks.