0

If I want to block all of the IP addresses for 192.0.2.1 through 192.0.2.255 I can simply do the following:

Deny from 192.0.2

...by simply omitting the last/fourth octet. However what if I want to block 192.0.2.120 through 192.0.2.250? I can't test what I've seen (that I know of) so I don't want to block 192.0.2.119 or 192.0.2.251.

So how do I block the appropriate range without blocking other IP addresses or having to list like a hundred IP addresses in the .htaccess file?


Clarification: I learn better through a more brute-force iterative style. So having multiple examples helps me quickly connect how things work. In example:

192.0.2.4 - 192.0.2.12

192.0.2.68 - 192.0.2.103

192.0.2.145 - 192.0.2.222

In other words I derive the methodology through having an answer that I can easily comprehend.

  1. So with the first example last-octet of 4-12 (based on the suggested thread) I'm guessing 4 * 8 = 32 so ".4" would be /32?

  2. If correct how do I specify the range to 12?

  3. 8 * 12 = 96 would be /96? So 192.0.2/32/96?

So to block the range of 192.0.2.4 through 192.0.2.12 without blocking .3 or .13 my current guess would be 192.0.2/32/96. Please keep in mind that it's as important to not block innocent IP addresses to me as it is to block offending IP addresses, that clarification seems to be lacking when I read related material.

John
  • 138
  • 11

1 Answers1

6

First of all, Deny and Allow directives are provided by mod_access_compat and are deprecated (provided you use Apache 2.4, which you should; it's off topic to ask here about ancient unsupported versions of the software anyway). Don't use them.

You should use Require directive provided by mod_authz_core module instead, and for setting up access by IP address, e.g. to use host authorization, you use Require ip provided by mod_authz_host module.

Also, you shouldn't use .htaccess files either. As stated in the manual:

You should avoid using .htaccess files completely if you have access to httpd main server config file. Using .htaccess files slows down your Apache http server. Any directive that you can include in a .htaccess file is better set in a Directory block, as it will have the same effect with better performance.

... and you certainly must have an access to the httpd main server config to ask here (else, again, it would be off topic on ServerFault). So, basically, following developer's recommendations (which we adhere to), .htaccess files are discouraged.


Then, revise the link in the comment. It explains how subnetting works, or "what is a perfect subnet". In short, it's the one you can write in CIDR form. For exapmple, 192.168.10.128/28 contains an address range 192.168.10.128 ÷ 192.168.10.143 (inclusive). Only such blocks can be expressed in the Require ip syntax. Notice that 192.0.2.0 is a valid IP address, in that IP packets with similar source or destination can appear, and your first range must be from 0 to 255, not from 1.

So, you need to split your imperfect range into series of perfect CIDR blocks. Your first provided case (which I had to edit, because the way it was expressed in the question was incorrect), 192.0.2.120 ÷ 192.0.2.250 (inclusive), that would translate into the following series of CIDR blocks:

  • 192.0.2.120/29 (covers hosts from .120 to .127 inclusive)
  • 192.0.2.128/26 (from .128 to .191)
  • 192.0.2.192/27 (from .192 to .223)
  • 192.0.2.224/28 (from .224 to .239)
  • 192.0.2.240/29 (from .240 to .247)
  • 192.0.2.248/31 (.248 and .249)
  • 192.0.2.250 (/32, a single address)

When creating such lists, IP subnetting calculators (like this) are very useful.

An algorithm is pretty simple: you start with the first host from your wanted range and find out the longest CIDR mask length that doesn't cover any extra (it will be /32 if the address is odd, for example). It gives you some starting block. Then you go on with the address next to the last address your first block has covered and repeat this process until you have all your range covered.


You may express this as in a single directive:

Require not ip 192.0.2.120/29 192.0.2.128/26 192.0.2.192/27 \
               192.0.2.224/28 192.0.2.240/29 192.0.2.248/31 192.0.2.250

and I believe it's the shortest way to disable such a range.

Alternatively, you can split it into a few directives using <RequireAll> block:

<RequireAll>
    Require not ip 192.0.2.120/29
    Require not ip 192.0.2.128/26
    Require not ip 192.0.2.192/27
    Require not ip 192.0.2.224/28
    Require not ip 192.0.2.240/29
    Require not ip 192.0.2.248/31
    Require not ip 192.0.2.250
    Require all granted
</RequireAll>

If none of the directives contained within the <RequireAll> directive fails, and at least one succeeds, then the <RequireAll> directive succeeds. If none succeed and none fail, then it returns a neutral result. In all other cases, it fails.

In this case, last always succeeds, but if one of previous fail, the whole block returns failure.