Understanding Apache’s Order/Allow/Deny Directives: Best Practices for Access Control


8 views

The Order directive in Apache determines the sequence in which Allow and Deny rules are processed. There are two possible combinations:

Order Allow,Deny  # Allow rules are evaluated first, then Deny rules
Order Deny,Allow  # Deny rules are evaluated first, then Allow rules

The current setup in your Directory block is actually quite permissive:


    Options -Indexes -FollowSymLinks MultiViews
    AllowOverride None
    Order Allow,Deny
    Allow from all

This configuration means:

  • All requests are allowed by default (Allow from all)
  • No subsequent deny rules exist to restrict access
  • The order is evaluated as: first check allow rules, then deny rules

For production environments, consider these alternatives:

# Option 1: Restrict to localhost only
Order Deny,Allow
Deny from all
Allow from 127.0.0.1 ::1

# Option 2: Allow specific IP ranges
Order Allow,Deny
Allow from 192.168.1.0/24
Deny from all

Your Files block implementation is correct but could be optimized:


    RewriteEngine Off

    # Default deny all
    Order Deny,Allow
    Deny from all

    # Exception for static assets
    
        Allow from all
    

Key improvements:

  • Simplified to single Order directive
  • Changed evaluation order for better security
  • Removed redundant directives

For newer Apache versions, consider using the more intuitive Require syntax:


    Require all denied
    Require local  # Allow localhost
    # OR for specific IPs:
    Require ip 192.168.1.0/24

Example 1: Restrict admin area


    Order Deny,Allow
    Deny from all
    Allow from 203.0.113.5

Example 2: Public assets with IP logging


    Order Allow,Deny
    Allow from all
    Deny from 123.45.67.89
    SetEnvIfNoCase Remote_Addr ^(.*)$ tracked_ip=$1
    CustomLog logs/asset_access.log combined env=tracked_ip


The Order directive in Apache determines the sequence of processing allow/deny rules. The syntax Order Allow,Deny means:

1. Process ALL Allow rules first
2. Then process ALL Deny rules
3. The last matching rule wins

Your current configuration:

<Directory />
    Options -Indexes -FollowSymLinks MultiViews
    AllowOverride None
    Order Allow,Deny
    Allow from all
</Directory>

This setup allows access from all IPs because the Allow from all is the last matching rule. If you want to restrict access:

<Directory />
    Options -Indexes -FollowSymLinks MultiViews
    AllowOverride None
    Order Deny,Allow
    Deny from all
    Allow from 127.0.0.1
</Directory>

For your /var/www/example/subdomains/dev/public/webapp directory, consider this improved version:

<Directory /var/www/example/subdomains/dev/public/webapp>
    RewriteEngine Off
    
    # Default deny all
    Require all denied
    
    # Allow specific file types
    <FilesMatch "\.(png|gif|jpe?g|css|js|swf|ps|flv)$">
        Require all granted
    </FilesMatch>
</Directory>

Since Apache 2.4, the recommended syntax uses Require:

<Directory />
    Options -Indexes -FollowSymLinks
    AllowOverride None
    Require all denied
    # For specific IP:
    Require ip 192.168.1.0/24
    Require ip 127.0.0.1
</Directory>

Example 1: Allow only local network

Order Deny,Allow
Deny from all
Allow from 192.168.1.0/24
Allow from 127.0.0.1

Example 2: Block specific user agents

<Directory /wp-admin/>
    Order Allow,Deny
    Allow from all
    Deny from env=bad_bot
</Directory>

SetEnvIfNoCase User-Agent "BadBot" bad_bot

When using Order directives, Apache must evaluate each rule sequentially. For complex configurations:

  • Place more specific rules first
  • Combine multiple IPs in single statements when possible
  • Consider using FilesMatch instead of multiple Files directives

The most efficient modern equivalent would be:

<Directory /protected/>
    Require ip 192.168.1 10.0.0.0/8
    Require not ip 192.168.1.99
</Directory>