Apache LimitExcept GET to IP address but deny all methods to other IPs

6,108

When you use Order Deny,Allow the Allow from all will override any Deny from ....

The default behaviour with Order Deny,Allow in the event of no match is to "allow". Does it work closer to expected if you remove "Allow from all"?

Each <Directory> also inherits ancestor (i.e. shorter path) <Directory> settings, so the <LimitExcept> applies to the other <Directory> sections too. You cannot simply undo this by adding

<Limit GET HEAD>
    Allow from all
</Limit> 

to those, because that will undo your blocking of the bad IP addresses there too. (I don't know if you need to undo it on your website though.)

The important things to remember about Order/Allow/Deny are:

  • this is not first-match logic like conventional access control
  • the Allow and the Deny are both checked for any match
  • which one wins (Allow or Deny) and what the default is both depend on the Order.

It's not a great idea to have duplicate <Directory ...> blocks, but if you do they are processed in the order they appear in the config.

See the Apache docs for the full logic: http://httpd.apache.org/docs/2.2/sections.html

Since your requirements don't quite fit simple allow/deny logic you should look at using either or both of:

  • SetEnvIf and Allow from env=... Deny from env=...
  • mod_rewrite

This is one way of doing it:

RewriteEngine on
RewriteCond %{REMOTE_ADDR}    1.1.1.1 [OR]
RewriteCond %{REMOTE_ADDR}    2.2.2.2 [OR]
RewriteCond %{REMOTE_ADDR}    3.3.3.3 
RewriteRule .                 -       [F]

Place that in your <Virtualhost> outside and </Directory> containers. Should the list of IPs be large or volatile you can also use RewriteMap and a variation on the above to keep IPs in a separate file as a more scalable solution.

Share:
6,108

Related videos on Youtube

batfastad
Author by

batfastad

Updated on September 18, 2022

Comments

  • batfastad
    batfastad over 1 year

    I'm having some trouble with getting the Order directive right in a vhost configuration in Apache.

    I have some IP addresses that I want to totally deny access to the entire vhost. These have been previously flagged as malicious.
    I also want to deny all requests apart from GET and HEAD from all IP addresses, apart from our internal IP range.

    I'm having trouble with the first Directory directive and figuring out how is best to arrange it with the Order directive.

    This is what I've got so far and it doesn't appear to work so I'd like to get some advice on how is best to order this block...

    NameVirtualHost *:80
    <VirtualHost *:80>
            ServerName      www.test.com
            ServerAlias     test.com
    
            DocumentRoot    /var/www/html/www.test.com
    
            <Directory      /var/www/html/www.test.com>
                    Options +FollowSymLinks
    
                    Order Deny,Allow
    
                    # Deny suspect IPs previously flagged
                    Deny from 111.111.111.111
                    Deny from 222.222.222.222
                    Deny from 333.333.333.333
    
                    # But only internal IPs can POST
                    <LimitExcept GET HEAD>
                        Deny from all
                        Allow from 10.10.0.0/22
                    </LimitExcept>
    
                    Allow from all
    
            </Directory>
    
        # CLI directory not web accessible
            <Directory      /var/www/html/www.test.com/cli>
                    Order Deny,Allow
                    Deny from all
            </Directory>
    
    
            # Restrict access to admin internal IPs only
            <Directory      /var/www/html/www.test.com/admin>
                    Order Deny,Allow
                    Deny from all
                    Allow from 10.10.0.0/22
            </Directory>
    
    </VirtualHost>

    My head is so scrambled with this now that I'm unable to see it clearly. Anyone know how to do this?

    Can I use multiple Directory directives for the same directory?
    So I separate out my denying the malicious IPs from the denying all requests apart from GET and HEAD?