It’s very easy to make mistakes with the htaccess Order directive, so if it’s not working here’s some tips to fix it (for Apache web servers).
If we get the ‘Deny, Allow’ bit the wrong way round it won’t do what we expect – at best it will do nothing, at worst it denies everybody access to our site. So tread carefully, keep a backup and test after making changes 🙂
IMPORTANT: Also see below as the order directive has been deprecated and there is a newer way to do this.
‘Order’ in htaccess does not work like other kinds of regular expressions (regex).
Key Point 1: Apache always makes THREE passes of the access statements.
It does NOT find the first match and then stop – and that’s what makes things go haywire if we’re not careful.
Why Is It Not Working!?
Here’s a typical “block some IP’s because they keep spamming my WordPress comments” htaccess:-
Order Deny, Allow Deny from 173.44.37. Deny from 184.108.40.206 Allow from all
Looks OK right? It’s allowing everything, but blocking a specific IP address, and an IP range (everything starting with 173.44.37).
Problem is – this does NOT work!
Look closer at that Order statement – Deny first, then Allow.
Key Point 2: This is NOT the order the statements are written. It’s the order in which they will be PROCESSED.
This is what actually happens in this case:-
- Apache processes the Deny statements
- Then processes the Allow statements
- Finally processes anything that doesn’t match either of these
But remember – as I said above, Apache does ALL three of these passes. It does NOT just exit at the first one matched.
So in this example:-
For our regular nice visitor, Apache doesn’t match any denied IP addresses on Pass 1. And then hits the ‘Allow All’ statement on Pass 2. Because we have used ‘All’ here, it matches. There’s no match on Pass 3 because we already matched on Pass 2. So the request is allowed.
If it’s one of our spammers however, Apache does match the IP whilst processing the deny statements. Great, so far so good. But then it processes the Allow statement and is told to ‘Allow All’ – BAM, we just let our spammer back in again!
That’s not what we intended. But the only way we’d know it wasn’t working was if we noticed the spam was still coming from those ‘blocked’ IP addresses!
How To Fix It!
In this case, the fix is as simple as reversing the Order statement. If we simply switch to ‘Order Allow, Deny’ to process the Allow statements first – now things should behave as expected, i.e.
Our spammer arrives. Apache checks for Allow statements, finds an ‘Allow All’ so initially flags the request to be allowed. But then makes a 2nd pass to check the Deny statements. Now it finds a match for the spammer’s IP address, and changes the flag to deny the request instead. The request is blocked.
For our nice visitor, the Allow matches and the Deny doesn’t. The request is Allowed.
Bottom line. The order of ‘Order’ is critical. So be very careful when copying htaccess snippets from other sites, as they may not behave quite as you might expect.
P.S. Don’t forget the 3rd pass entirely. If you’re NOT using an ‘All’ statement somewhere (either in an Allow or Deny) this WILL come into play.
The 3rd case defaults to the SECOND directive – being Allow or Deny depending on what Order you have them.
So for ‘Order Allow, Deny’ where there is no match for either case, the request will default to being Denied. More examples of that another time…
UPDATE: The New Easier Way
Thankfully the whole order directive is going away. It’s deprecated and will be removed from Apache eventually.
This is the new way to block an IP (available since Apache v2.4):-
Require all granted
Require not ip 220.127.116.11
Or the other popular use for these directives is to only allow certain IP addresses (e.g. to particular folders, or during maintenance etc). To do that simply use:-
Require ip 18.104.22.168
So remember, the old ‘order deny, allow’ is going away – start using this method now to prevent sites breaking in the future when Apache is upgraded.