Throughout the book, I explain various techniques for controlling access to web pages. For example, if you are getting hit with an attack from a specific range of IP addresses, you can add directives to block them based on the host address or other variables. It is a common technique that I've discussed numerous times. With Apache 2.4, there are changes to the directives that are used for access control. This tutorial explains the changes and then shares some examples to help you implement the best solution for your site.
Note: this topic is covered in the book on page 147, "Allow/Deny directives for Apache 2.4+" (in Chapter 7: Tighten Security).
Changes in Apache 2.4
Apache 2.2 uses the authz_host_module to control access using directives like
So basically, the rules to control access are different depending on your version of Apache. To help with this, I've provided numerous examples below.
Here are some examples that compare the different syntax required depending on your version of Apache.
Important! Do not use 2.2 and 2.4 directives on the same server; it may cause issues and/or errors. A workaround for this is to use Conditional Directives, as explained below.
Deny all requests
# DENY ALL REQUESTS # Apache 2.2 Order deny,allow Deny from all # Apache 2.4+ Require all denied
Allow all requests
# ALLOW ALL REQUESTS # Apache 2.2 Order allow,deny Allow from all # Apache 2.4+ Require all granted
Deny access based on host name
# DENY ACCESS TO EXAMPLE.COM # Apache 2.2 Order Allow,Deny Allow from all Deny from example.com # Apache 2.4+ <RequireAll> Require all granted Require not host example.com </RequireAll>
Require all granted are required when doing anything more than either
Require all granted or
Require all denied (as shown in the above examples). Here a couple more examples to further illustrate the concept using Require/All.
Deny access based on IP address
# DENY ACCESS TO IP ADDRESS # Apache 2.2 Order Allow,Deny Allow from all Deny from 18.104.22.168 Deny from 22.214.171.124 Deny from 126.96.36.199 # Apache 2.4+ <RequireAll> Require all granted Require not ip 188.8.131.52 Require not ip 184.108.40.206 Require not ip 220.127.116.11 </RequireAll>
Deny access to specific file
# DENY ACCESS TO FILE # Apache 2.2 <Files ~ "example\.txt"> Order Allow,Deny Allow from all Deny from 18.104.22.168 </Files> # Apache 2.4+ <Files ~ "example\.txt"> <RequireAll> Require all granted Require not ip 22.214.171.124 </RequireAll> </Files>
Reminder: Do not use both 2.2 and 2.4 directives on the same server. Doing so may cause errors. Use only the code that applies to your version of Apache. Or, if you want to create a modular, plug-n-play snippet that can be added to any Apache version 2.2 or 2.4+, check out the conditional directives technique in the next section.
Example: Conditional Directives
In some cases, you may not know which version of Apache you are using. In such case, the following conditional directives should give you a better idea. You can use the following code on any Apache server version 2.2 or 2.4+.
# Apache 2.2 <IfModule !authz_core_module> Order Deny,Allow Deny from all Allow from 126.96.36.199 </IfModule> # Apache 2.4+ <IfModule authz_core_module> <RequireAll> Require ip 188.8.131.52 </RequireAll> </IfModule>
When included via .htaccess or Apache configuration file, this code will detect the correct version of Apache and use the proper directives for access control. Here's how it works:
If the server is Apache 2.2 then we know that
authz_core_module does not exist. So any directives included inside of the first
<IfModule> container will be executed only on Apache 2.2.
Or if the server is Apache 2.4+ we know that
authz_core_module exists. So any directives included inside of the second
<IfModule> container will be executed only on Apache 2.4 and better.