Home > OS >  RewriteRule depending on HTTP_REFERER and REMOTE_ADDR
RewriteRule depending on HTTP_REFERER and REMOTE_ADDR

Time:06-23

I need to redirect users to a specific page if they are not coming from a specific IP and if they are requesting a specific domain.

I tried :

RewriteEngine On
RewriteCond %{HTTP_REFERER} ^hello\.example\.com [NC] # the user requested https://hello.example.com
RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.99 # the user's IP is not 123.456.789.99
RewriteCond %{REQUEST_URI} !/maintenance.html$ [NC] # the user is not already on the redirected page
RewriteRule .* /maintenance.html [R=302,L]

But it does not work...

Help?

CodePudding user response:

The HTTP_REFERER contains the referring URL (the contents of the Referer HTTP request header, ie. the URL the user is coming from), not the domain being requested. For that you need to test against the HTTP_HOST server variable (ie. the Host HTTP request header) instead.

Note also that Apache does not support line-end comments - your second condition (as written) would result in a 500 Internal Server Error due to an invalid flags argument.

There is no need for the 3rd condition that checks that the requested URL is not /maintenance.html as this can more efficiently be checked in the RewriteRule itself.

Try the following instead:

RewriteCond %{HTTP_HOST} ^hello\.example\.com [NC]
RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.99$
RewriteRule !maintenance\.html$ /maintenance.html [NC,R=302,L]

Note that the URL-path matched by the RewriteRule pattern does not start with a slash.

Aside: For checking single IP addresses, it is often easier/cleaner to use a lexicographical string comparison (using the = prefix operator), rather than a regex. For example:

:
RewriteCond %{REMOTE_ADDR} !=123.456.789.99
:

However, if you are implementing a temporary "under maintenance" page then consider sending a 503 Service Unavailable response instead.

Reference:

  • Related