SetEnvIf and SetEnvIfNoCase are really useful directives supplied by the mod_setenvif module that allow you to conditionally set environment variables accessible by scripts and apache based on the value of HTTP Headers, Other Variables, and Request information.
For debugging, you may want to use my server environment variable debugging script
- Unique mod_setenvif Variables
- Populates HTTP_MY_ Variables with mod_setenvif variable values
- Set REMOTE_HOST to HTTP_HOST
- Allows only if HOST Header is present in request
- Add values from HTTP Headers
- Set the REDIRECT_STATUS for Interpreter Security
- Block Bad Bots
- Allow Search robots
- SetEnvIf Directive
These can be used for
- the hostname (if available) of the client making the request -
- IP address of the client making the request -
- IP address of the server on which the request was received -
- name of the method being used -
- name and version of the protocol with which the request was made -
- the resource requested on the HTTP request line -- generally the portion of the URL following the scheme and host portion without the query string -
SetEnvIf attribute regex [!]env-variable[=value] [[!]env-variable[=value]] ...
SetEnvIfNoCase Remote_Host "(.*)" HTTP_MY_REMOTE_HOST=$1 SetEnvIfNoCase Remote_Addr "(.*)" HTTP_MY_REMOTE_ADDR=$1 SetEnvIfNoCase Server_Addr "(.*)" HTTP_MY_SERVER_ADDR=$1 SetEnvIfNoCase Request_Method "(.*)" HTTP_MY_REQUEST_METHOD=$1 SetEnvIfNoCase Request_Protocol "(.*)" HTTP_MY_REQUEST_PROTOCOL=$1 SetEnvIfNoCase Request_URI "(.*)" HTTP_MY_REQUEST_URI=$1
Sets REMOTE_HOST to www.askapache.com if Remote_Addr=188.8.131.52. This can be useful if your server doesn't automatically do a reverse lookup on a remote address, so this way you can tell if the request was internal/from your server.
SetEnvIf Remote_Addr 184.108.40.206 REMOTE_HOST=www.askapache.com
SetEnvIfNoCase ^HOST$ .+ HTTP_MY_HAS_HOST Order Deny,Allow Deny from All Allow from env=HTTP_MY_HAS_HOST
SetEnvIfNoCase Host .+ HTTP_MY_HAS_HOST Order Deny,Allow Deny from All Allow from env=HTTP_MY_HAS_HOST
SetEnvIfNoCase ^If-Modified-Since$ "(.+)" HTTP_IF_MODIFIED_SINCE=$1 SetEnvIfNoCase ^If-None-Match$ "(.+)" HTTP_IF_NONE_MATCH=$1 SetEnvIfNoCase ^Cache-Control$ "(.+)" HTTP_CACHE_CONTROL=$1 SetEnvIfNoCase ^Connection$ "(.+)" HTTP_CONNECTION=$1 SetEnvIfNoCase ^Keep-Alive$ "(.+)" HTTP_KEEP_ALIVE=$1 SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1 SetEnvIfNoCase ^Cookie$ "(.+)" HTTP_MY_COOKIE=$1
This is useful in disallowing direct access to interpreters like shell scripts, cgi scripts, and other interpreters. Only works this way if you have a static IP for your server. So the only way to access these files is by instructing the server itself to request the file, using an Action directive or by requesting the file through a .php or other script using curl or wget, or something like fsockopen.
<FilesMatch "\.(cgi|sh|pl)$"> SetEnvIfNoCase Remote_Addr 220.127.116.11 REDIRECT_STATUS Order Deny,Allow Deny from All Allow from env=REDIRECT_STATUS </FilesMatch>
Can be useful if your site is getting hammered by spambots. Some nice examples from around the net are at Fight Blog Spam With Apache... Keep in mind the HTTP_USER_AGENT is directly from the client, so its easy to spoof / change. Instead use mod_security for a much better solution.
SetEnvIfNoCase User-Agent "^Bandit" bad_bot SetEnvIfNoCase User-Agent "^Baiduspider" bad_bot SetEnvIfNoCase User-Agent "^BatchFTP" bad_bot SetEnvIfNoCase User-Agent "^Bigfoot" bad_bot SetEnvIfNoCase User-Agent "^Black.Hole" bad_bot Order Allow,Deny Allow from All Deny from env=bad_bot
This does the opposite of above, allowing ONLY these web robots access. Other than rogue robots, configuring your robots.txt file correctly will keep most robots where you want them.
SetEnvIfNoCase User-Agent .*google.* search_robot SetEnvIfNoCase User-Agent .*yahoo.* search_robot SetEnvIfNoCase User-Agent .*bot.* search_robot SetEnvIfNoCase User-Agent .*ask.* search_robot Order Deny,Allow Deny from All Allow from env=search_robot
|Description:||Sets environment variables based on attributes of the request|
|Context:||server config, virtual host, directory, .htaccess|
SetEnvIf directive defines environment variables based on attributes of the request. The attribute specified in the first argument can be one of three things:
- An HTTP request header field (see RFC2616 for more information about these); for example:
Accept-Language. A regular expression may be used to specify a set of request headers.
- One of the following aspects of the request:
Remote_Host- the hostname (if available) of the client making the request
Remote_Addr- the IP address of the client making the request
Server_Addr- the IP address of the server on which the request was received (only with versions later than 2.0.43)
Request_Method- the name of the method being used (
POST, et cetera)
Request_Protocol- the name and version of the protocol with which the request was made (e.g., "HTTP/0.9", "HTTP/1.1", etc.)
Request_URI- the resource requested on the HTTP request line -- generally the portion of the URL following the scheme and host portion without the query string. See the
mod_rewritefor extra information on how to match your query string.
- The name of an environment variable in the list of those associated with the request. This allows
SetEnvIfdirectives to test against the result of prior matches. Only those environment variables defined by earlier
SetEnvIf[NoCase]directives are available for testing in this manner. 'Earlier' means that they were defined at a broader scope (such as server-wide) or previously in the current directive's scope. Environment variables will be considered only if there was no match among request characteristics and a regular expression was not used for the attribute.
The second argument (regex) is a regular expression. If the regex matches against the attribute, then the remainder of the arguments are evaluated.
The rest of the arguments give the names of variables to set, and optionally values to which they should be set. These take the form of
In the first form, the value will be set to "1". The second will remove the given variable if already defined, and the third will set the variable to the literal value given by
value. Since version 2.0.51 Apache will recognize occurrences of
$9 within value and replace them by parenthesized subexpressions of regex.
SetEnvIf Request_URI ".gif$" object_is_image=gif SetEnvIf Request_URI ".jpg$" object_is_image=jpg SetEnvIf Request_URI ".xbm$" object_is_image=xbm SetEnvIf Referer www.askapache.com intra_site_referral SetEnvIf object_is_image xbm XBIT_PROCESSING=1 SetEnvIf ^SETENVIF* ^[a-z].* HAS_SETENVIF
The first three will set the environment variable
object_is_image if the request was for an image file, and the fourth sets
intra_site_referral if the referring page was somewhere on the
www.askapache.com Web site.
The last example will set environment variable
HAS_SETENVIF if the request contains any headers that begin with "SETENVIF" whose values begins with any character in the set [a-z].