5

I'd like to dynamically add IPs to a block list via htaccess. I was hoping someone could tell me if the following will work in my case (I'm unsure how to test via localhost).

My .htaccess file will have the following by default:

order allow,deny
allow from all

IPs will be dynamically appended:

Order Deny,Allow
Allow from all
Deny from 192.168.30.1

The way I understand this is that it is by default allow all with the optional list of deny rules. If I'm not mistaken Order Deny,Allow will look at the Deny list first, is this correct?

And does the Allow from all rule need to be at the end?

EDIT 1

If I'm not mistaken I need to do this based on jeffatrackaid's answer:

Order Allow,Deny
Allow from all
Deny from 192.168.30.1

EDIT 2

For the sake of completeness, this is probably more appropriate for my requirements:

Order Deny,Allow
Deny from 192.168.30.1

2 Answers 2

7

This rule allows everyone into your site.

Order Deny,Allow
Allow from all
Deny from 192.168.30.1

The Order directive determines the order in which your rules are processed. With Order deny,allow the deny list will be processed first then the allow list.

With Apache, all rules are processed with the last one matching being the effective rule.

So in this case, your last rule would be allow from all.

This means that 192.168.30.1 would initially be denied but then allowed since the allow rules are processed last.

This would produce the same result

Order Deny,Allow
Allow from all
Deny from 192.168.30.1
Allow from 192.168.30.1

Think of it this way.

  • The allow/deny rules are simply separate lists of IPs to be allowed/denied.
  • The order directive determines the order in which these lists are processed.
  • Apache evaluates all rules and acts on the result of the last matching rule.

The major confusion is that this is very different from how firewalls work where rule order and first match is often what determines access.

See: http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#order

2
  • Thnaks for the detailed explanation. I was under the impression that 'deny, allow' will always apply the deny rule, even on subsequent attempts. Any recommendations on how I can achieve this? Jun 9, 2014 at 22:15
  • Your updated code allow,deny should work. The allow list is processed first followed by the deny list. So if an IP is listed in the deny list it will be blocked since it will be last matched. Just one note, if you have too many deny rules you may see performance issues. All rules are processed on every request. "Too many" depends on your hardware and server loads but something to keep in mind with any tool that auto-adds rules to .htaccess. Jun 10, 2014 at 20:54
0

In the configuration file, e.g., .conf, if you have:

Order Deny,Allow 
Allow from all 
Deny from 192.168.30.1 

The user wanted to block the access to only one IP, 192.168.30.1, but allowing access to the rest.

Reality: Apache grants access to all IP address, exposing a severe security threat and is entirely opposite of the user’s intent.


Root Cause: the entry Order plays the key role: it decides the order in which the functions deny and allow are executed. If the value of Order is set to deny,allow, any IP address matching the value specified in the entry Deny from gets a temporary return value deny. After that it is checking the entry Allow from, and if it matches, it receives the return value allow, that overwrites the previous value. 
 Looking at the source code snippet in Apache (see below), you can find that why 192.168.30.1 is not blocked by Apache.

int ret = OK; // default

if (a->order[method]==ALLOW_THEN_DENY) { 
    ret = HTTP_FORBIDDEN;
  
    if (find_allowdeny(r,a-> allows,method)) 
        ret = OK;
  
    if (find_allowdeny(r,a-> denys,method)) 
        ret = HTTP_FORBIDDEN;}

else if (a->order[method]== DENY_THEN_ALLOW) { 
    if (find_allowdeny(r,a-> denys,method)) 
        ret = HTTP_FORBIDDEN;

    if (find_allowdeny(r,a-> allows,method)) 
        ret = OK;} 
else
   
   { if (find_allowdeny(r,a-> allows,method) && !find_allowdeny(r,a-> denys,method)) 
    ret = OK; 
else
   
    ret = HTTP_FORBIDDEN;} 

The correct version of this configuration would be:

Order Deny,Allow 
Deny from 192.168.30.1 

or just a single line of

Deny from 192.168.30.1 

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .