Thanks Luca.   This all makes sense with what I was seeing.   I ended up using 
something similar to what you suggested.   Here it is in case it ever helps 
someone.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '10.0.0.0/8' && \
! %{HTTP:X-Real-IP}  -ipmatch '172.16.0.0/12' && \
! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16' && \
! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8' ">
  ErrorDocument 400 /errors/400
  ErrorDocument 401 /errors/401
  ErrorDocument 402 /errors/402
  ErrorDocument 403 /errors/403
  ErrorDocument 404 /errors/404
  ErrorDocument 405 /errors/405
  ErrorDocument 500 /errors/500
  ErrorDocument 501 /errors/501
  ErrorDocument 502 /errors/502
  ErrorDocument 503 /errors/503
  ErrorDocument 504 /errors/504
  ErrorDocument 505 /errors/505
</If>



From: Luca Toscano [mailto:toscano.l...@gmail.com]
Sent: Tuesday, February 21, 2017 11:46 AM
To: users@httpd.apache.org
Subject: Re: [users@httpd] Problem when using nested if statements in apache 2.4

Hi Mike,

2017-02-20 18:17 GMT+01:00 Mike Schlottman 
<mschl...@spe.org<mailto:mschl...@spe.org>>:
I’m trying to configure apache 2.4 to show nice error pages to external users 
of our web site, while allowing staff to see the real error.   The idea is to 
prevent exposing privileged information to the general public while allowing 
our staff to more easily debug issues on our production web site.   To 
accomplish this I am using a combination of ErrorDocument within an If 
statement that evaluates the header X-Real-IP which is the IP address of the 
client on my server.

This seems to work, until I nest the If statements to catch all the IP ranges 
that I am interested in.

For example…
<If  "! %{HTTP:X-Real-IP}  -ipmatch '172.28.1.84/32<http://172.28.1.84/32>' ">
  ErrorDocument 404 /errors/404
</If>
will correctly show the nice 404 page for a user coming from 172.28.1.84.

Using this, the same user coming from 172.28.1.84 sees the nice error page.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8<http://127.0.0.0/8>' ">
  ErrorDocument 404 /errors/404
</If>

Simmilarly the same user gets the nice error page when this code is used.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16<http://192.168.0.0/16>' ">
  ErrorDocument 404 /errors/404
</If>

The problem comes when I combine these 2 so that all users except those coming 
from 127.*.*.* or 192.168.*.* see the nice error page.
<If  "! %{HTTP:X-Real-IP}  -ipmatch '127.0.0.0/8<http://127.0.0.0/8>' ">
  <If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16<http://192.168.0.0/16>' ">
    ErrorDocument 404 /errors/404
  </If>
</If>
The user from 172.28.1.84 does not get the nice 404 page, but the default 404 
page.   The IP does not match either of the ranges as observed when using the 
ranges individually, but when combined in this way it does not work as expected.

Any ideas why this is?


I reproduced your use case and from the error_log (trace8) I can see that with 
nested <If>s the second one seems not evaluated (or more precisely, its 
expression is not). In the beginning I thought it was a peculiarity of how the 
ErrorDocument core directive settings are merged between sections, but it seems 
not the case.

From my point of view, a container like <If> should be used like other similar 
directives like <Directory> and <Location>, where this use case would look a 
bit weird. The <If> naming brings up conventions that we use in traditional 
programming languages, so this might be the source of the confusion.

For your specific use case, I'd have done something like the following:

<If  "! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16<http://192.168.0.0/16>'  || 
! %{HTTP:X-Real-IP}  -ipmatch '192.168.0.0/16<http://192.168.0.0/16>' ">
    ErrorDocument 404 "My awesome error"
</If>

or maybe using <ElseIf>/<Else>.

http://httpd.apache.org/docs/current/sections.html shows a little paragraph 
about "Nesting of sections", but I don't see any reference of your use case. 
I'll dig a bit more during the next days to find a better explanation if nobody 
will come up with a better solution :)


Luca


Reply via email to