42

I would like to allow only one country access, but exclude proxies within this country.

This is what I have (shortened version for convenience)

<Limit GET POST>
order deny,allow
deny from all
allow from 139.82.0.0/16
allow from 143.54.0.0/16
allow from 186.192.0.0/11
allow from 186.224.0.0/11
.
deny from 186.201.27.66
deny from 186.201.196.1
deny from 186.214.51.231
deny from 186.237.225.26
</Limit>

But I know this wont work. How do I go about doing this?

regilero
  • 29,806
  • 6
  • 60
  • 99
Gaia
  • 2,872
  • 1
  • 41
  • 59
  • 1
    of course, but in this case the (proxy) last deny group IPs are WITHIN the allowed IPs, which will be processed last. – Gaia Mar 30 '12 at 16:05
  • Just use `order allow,deny` instead. – Gerben Mar 31 '12 at 18:27
  • Like this? `order allow,deny allow from 139.82.0.0/16 allow from 143.54.0.0/16 allow from 186.192.0.0/11 allow from 186.224.0.0/11 . . . deny from 186.201.27.66 deny from 186.201.196.1 deny from 186.214.51.231 deny from 186.237.225.26 deny from all` since deny is processed last, wouldnt `deny from all` invalidate all the allows? – Gaia Apr 02 '12 at 18:01
  • I missed the `deny from all`. You'll need to remove that line entirely. To quote apache's docs. First, all Allow directives are evaluated; at least one must match, or the request is rejected. Next, all Deny directives are evaluated. If any matches, the request is rejected. Last, any requests which do not match an Allow or a Deny directive are denied by default. – Gerben Apr 03 '12 at 19:52
  • Thanks! Would you please confirm that "allow, deny" will work as intended as long as I dont use deny for all? – Gaia Apr 03 '12 at 20:35
  • Confimed. The rest of the code is okay. – Gerben Apr 04 '12 at 11:16
  • Thanks Gerden. I will test it then ask you to submit an answer so you can earn the bounty. – Gaia Apr 04 '12 at 16:33

6 Answers6

141

Update : for the new apache 2.4 jump directly to the end.

The Order keyword and its relation with Deny and Allow Directives is a real nightmare. It would be quite interesting to understand how we ended up with such solution, a non-intuitive one to say the least.

  • The first important point is that the Order keyword will have a big impact on how Allow and Deny directives are used.
  • Secondly, Deny and Allow directives are not applied in the order they are written, they must be seen as two distinct blocks (one the for Deny directives, one for Allow).
  • Thirdly, they are drastically not like firewall rules: all rules are applied, the process is not stopping at the first match.

You have two main modes:

The Order-Deny-Allow-mode, or Allow-anyone-except-this-list-or-maybe-not

Order Deny,Allow
  • This is an allow by default mode. You optionally specify Deny rules.
  • Firstly, the Deny rules reject some requests.
  • If someone gets rejected you can get them back with an Allow.

I would rephrase it as:

Rule Deny
     list of Deny rules
Except
     list of Allow rules
Policy Allow (when no rule fired)

The Order-Allow-Deny-mode, or Reject-everyone-except-this-list-or-maybe-not

Order Allow,Deny
  • This is a deny by default mode. So you usually specify Allow rules.
  • Firstly, someone's request must match at least one Allow rule.
  • If someone matched an Allow, you can still reject them with a Deny.

In the simplified form:

Rule Allow
     list of Allow rules
Except
     list of Deny rules
Policy Deny (when no rule fired)

Back to your case

You need to allow a list of networks which are the country networks. And in this country you want to exclude some proxies' IP addresses.

You have taken the allow-anyone-except-this-list-or-maybe-not mode, so by default anyone can access your server, except proxies' IPs listed in the Deny list, but if they get rejected you still allow the country networks. That's too broad. Not good.

By inverting to order allow,deny you will be in the reject-everyone-except-this-list-or-maybe-not mode. So you will reject access to everyone but allow the country networks and then you will reject the proxies. And of course you must remove the Deny from all as stated by @Gerben and @Michael Slade (this answer only explains what they wrote).

The Deny from all is usually seen with order deny,allow to remove the allow by default access and make a simple, readable configuration. For example, specify a list of allowed IPs after that. You don't need that rule and your question is a perfect case of a 3-way access mode (default policy, exceptions, exceptions to exceptions).

But the guys who designed these settings are certainly insane.

All this is deprecated with Apache 2.4

The whole authorization scheme has been refactored in Apache 2.4 with RequireAll, RequireAny and RequireNone directives. See for example this complex logic example.

So the old strange Order logic becomes a relic, and to quote the new documentation:

Controling how and in what order authorization will be applied has been a bit of a mystery in the past

kubanczyk
  • 5,184
  • 1
  • 41
  • 52
regilero
  • 29,806
  • 6
  • 60
  • 99
6

Not answering OPs question directly, but for the people finding this question in search of clarity on what's the difference between allow,deny and deny,allow:

Read the comma as a "but".

  • allow but deny: whitelist with exceptions.
    everything is denied, except items on the allow list, except items on the deny list
  • deny but allow: blacklist with exceptions.
    everything is allowed, except items on the deny list, except items on the allow list

allow only one country access, but exclude proxies within this country

OP needed a whitelist with exceptions, therefore allow,deny instead of deny,allow

Felk
  • 7,720
  • 2
  • 35
  • 65
3

Just use order allow,deny instead and remove the deny from all line.

Gerben
  • 16,747
  • 6
  • 37
  • 56
3

Change your code to

<Limit GET POST>
deny from all

allow from 139.82.0.0/16
allow from 143.54.0.0/16
allow from 186.192.0.0/11
allow from 186.224.0.0/11
</Limit>

This way your htaccess will deny every except those that you explicitly allow with allow from..

A proxy within the allow range can easily be overwritten with an additional deny from.. rule.

Gilly
  • 9,212
  • 5
  • 33
  • 36
2

As Gerben suggested, just change:

order deny,allow
deny from all

to

order allow,deny

And the restrictions will work as you want them to.

Details can be found in Apache's docs.

Michael Slade
  • 13,802
  • 2
  • 39
  • 44
0

In apache2, linux configuration

Require all granted

Deepa MG
  • 188
  • 1
  • 15