17 December 2021

Apache has two directives that can be used to block (or allow) an IP address. Traditionally, Apache used the Allow, Deny and Order directives, which are part of the mod_access_compat module. You can still use the directives, and there are plenty of tutorials that recommend them. However, the module has been deprecated in favour of mod_authz_host. I strongly recommend using the latter module’s directives, as the old ones will stop working in a future Apache version.

Blocking one or more IPs

To block an IP address you can use a rule like this:

<RequireAll>
  Require all granted
  Require not ip 1.2.3.4
</RequireAll>

The <RequireAll> directive specifies that none of the nested directives should fail. The two nested rules are fairly easy to understand. First, we allow all and sundry to access our website, and we next specify that the rule does not apply to the IP address 1.2.3.4.

You can add multiple IPs and use CIDR notation. For instance, here I block three IP addresses:

<RequireAll>
  Require all granted
  Require not ip 1.2.3.4 9.8.7.6 5.5.4.4
</RequireAll>

And here I block all IPs in the range 1.2.3.0 to 1.2.3.255:

<RequireAll>
  Require all granted
  Require not ip 1.2.3.4/24
</RequireAll>

Allowing one or more IPs

Denying all traffic apart from one or more specific IP addresses uses the same logic. You first deny all IP addresses and then specify which IP address(es) are allowed:

<RequireAll>
  Require all denied
  Require ip 1.2.3.4
</RequireAll>

You can use this technique to block or allow entire countries. However, there are problems with that approach. In particular, your .htaccess file will include a humongous list with CIDR ranges which you will need to keep up to date. If you really want to go down that route, you can get a list with IPv4 addresses at countryipblocks.net.