I am trying to get something working with mod_rewrite, but am not entirely sure it's even possible.
Say I have some request like:
https://www.example.com?h=somerandomvalue&u=www.another.example/content
I'd like to take the value of the u
parameter and rewrite the request using this value, so from the above example request, I'd like to rewrite it to be
https://www.another.example/content
So basically, request:
https://www.example.com?h=somerandomvalue&u=www.another.example/content
Redirects to:
www.another.example/content
Is this possible? I've seen other examples where people are capturing and using parameters as part of a rewritten path but I have not seen anything in the way of redirecting to an entirely new domain using the provided parameter.
Any help or guidance here is very much appreciated!
I've seen other examples where people are capturing and using parameters as part of a rewritten path
Yes, this is possible. The basic principle is the same:
RewriteEngine On
RewriteCond %{QUERY_STRING} (?:^|&)u=([\w./-]{6,})(?:&|$)
RewriteRule ^$ https://%1 [QSD,R=302,L]
%1
is a backreference to the capturing group in the preceding CondPattern. ie. the value of the u
URL parameter.
([\w./-]{6,})
is just a very rudimentary check to match a semi-valid URL. This can be improved.
The (?:^|&)
prefix on the regex ensures we only match the u
URL parameter and not any URL parameter that simply ends in u
.
This only redirects requests for the root, as in your example. A malicious user could turn your site into a relay to forward traffic.
However, without further validation of the URL being redirected to this is potentially open to abuse and should not be used.
UPDATE#1:
For example, you could limit the hostnames that can be redirected to with a series of RewriteCond
directives:
RewriteCond %{QUERY_STRING} (?:^|&)u=([\w./-]{6,})(?:&|$)
RewriteCond %1 ^(www\.another\.example/.*) [OR]
RewriteCond %1 ^(www\.two\.example/.*) [OR]
RewriteCond %1 ^(www\.three\.example/.*) [OR]
RewriteCond %1 ^(www\.four\.example/specific/path/to/file.html)
RewriteRule ^$ https://%1 [QSD,R=302,L]
The %1
backreference (which contains the captured group from the last matched CondPattern) matches the complete URL that is sent in the u
URL parameter. This relies on the fact that RewriteCond
directives finish "early" when the condition is satisfied.
If you have many specific URLs then you could create a RewriteMap
in the server config and perform a lookup to check the valid URLs.
Alternatively, rewrite the request to a server-side script (eg. PHP) and manage the checks and redirection in the script instead.
UPDATE#2:
Does this example also work if the u parameter is an encoded URL?
Not currently. The QUERY_STRING
server variable is not %-decoded. To allow a URL encoded (%-encoded) parameter value then you will need to include %
in the regex character class that matches the URL and include the NE
(noescape
) flag on the RewriteRule
directive to prevent any %-encoded characters being doubly encoded in the redirect response.
For example:
RewriteCond %{QUERY_STRING} (?:^|&)u=([\w%./-]{6,})(?:&|$)
:
RewriteRule ^$ https://%1 [NE,QSD,R=302,L]