Unfortunately, the Apache SetEnvIf module doesn’t support logical conditions, like
AND. More specifically, it is not possible to set a variable only if condition1 AND/OR condition2 are verified.
For example, to log all the POST queries made from the loopback interface in a separate log file, you can’t do this:
CustomLog /var/log/apache2/loopback_posts.log combined env=posting_myself SetEnvIf Remote_Addr "^127\.0\.0\.1$" AND Request_Method "POST" posting_myself
The first line is valid, it asks the server to log all the requests to the mentioned file, only if the environment variable
posting_myself is set.
The second line attemps to set the
posting_myself variable if two conditions are met (use of a logical AND), which is not a supported syntax.
On a first attempt to work around this problem, I came up with this (this does not work):
CustomLog /var/log/apache2/loopback_posts.log combined env=posting_myself SetEnv loopback_ip 0 SetEnvIf Remote_Addr "^127\.0\.0\.1$" loopback_ip=1 SetEnvIf Request_Method "POST" posting_myself SetEnvIf loopback_ip 0 !posting_myself
The first line is unchanged.
The second line unconditionally sets the variable
loopback_ip to zero (meaning : false).
The third line sets the same variable to one (“true”) if the requests indeed comes from the loopback IP.
The fourth line sets the variable
posting_myself to true if the request method is POST.
Note that at this stage, the
posting_myself variable can be true, even if somebody else made the request.
This is taken care of at the last line, where
posting_myself is unset if the variable
posting_myself is equal to zero (false).
After the last line, we will have the
posting_myself variable set only if the request comes from the loopback IP and if the request is a POST.
Unfortunately, this doesn’t work either, for a subtle reason : the
SetEnv directive is executed after the
SetEnvIf directives, according to the Apache documentation. This means that when
loopback_ip to zero, it’s way too late.
So, I came up with this other version to emulate a
SetEnvIf logical AND:
CustomLog /var/log/apache2/loopback_posts.log combined env=posting_myself SetEnvIf Remote_Addr "^" loopback_ip=0 SetEnvIf Remote_Addr "^127\.0\.0\.1$" loopback_ip=1 SetEnvIf Request_Method "POST" posting_myself SetEnvIf loopback_ip 0 !posting_myself
This is similar to the previous attempt, only the second line changes: I have to use
SetEnIfv, to artificially set
loopback_ip to zero, unconditionally. To do this, I use a regex that will always match : “^”. Note that I used
Remote_Addr, but I could have used
Request_URI or anything else: the only important thing is that it always matches and does set
loopback_ip to zero.
Now, to emulate a
SetEnvIf logical OR, this is way easier:
SetEnvIf Remote_Addr "^192\.168\.0\." my_networks SetEnvIf Remote_Addr "^127\.0\.0\.1$" my_networks
Here, the variable
my_networks will be set if the remote address starts with “192.168.0.” or is “127.0.0.1”. It’s that simple.
Well, I could have used a smarter regex to do this in one line, but it would have ruined my logical OR example! :)