LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Server
User Name
Password
Linux - Server This forum is for the discussion of Linux Software used in a server related context.

Notices


Reply
  Search this Thread
Old 07-21-2011, 11:36 AM   #1
helptonewbie
Member
 
Registered: Aug 2006
Location: England Somewhere
Distribution: Mandriva, PCLinuxOS, Karoshi, Suse, Redhat, Ubuntu
Posts: 518

Rep: Reputation: 39
Question Apache Server mod_Rewrite problem


Hi All,

I have a problem which might be a bug or it might be expected result i'm not sure and i've not been able to figure it out.

The set-up of web infrastructure is as follows.

websites1 -> Load balencer port 80 -> web server cluster port 80
websites2 -> Different load balencer port 80 -> Same Web server cluster port 81

So from this really basic example it should be obvious enough that we've split our web application/sites by port and that so things still work on the correct ports visibly we use multiple different load balancers so we still have 80 and 443 available to each app/site but it actually interacts with a different app/site underneith on the apache side of things as requests are directed to the correct apache port.

So problem is we have a redirect rule that basically says (in english) "ahh this request says .*/index.html redirect to /"

So that works as expected but when the request comes into apache on port 81 via load balancer websites2 we have un-expected results.. So imagine..
http://www.websites2.com -> Load Balencer (port 80) tcp redirects the request (nothing fancy happening at load balancer at all!) to port 81 on backend web cluster. OK apache answers it hits the re-write rule tries to send back as Location header of http://www.websites2.com:81.

Now :81 on the Location header.. big bad head ache... the port shouldn't be affected as we're using the loadbalencer that can answer port 80 requests not port 81.. why is apache adding port 81 into the redirect? Its not being told to do so etc.

Many Thanks,
M
 
Old 07-21-2011, 01:33 PM   #2
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
If you use an external redirection rule (R) with a path only, something like
Code:
RewriteRule ^.*/index.html$ / [R]
Apache will prepend the host name and port, if you have UseCanonicalPhysicalPort yes or ServerName yourserver:81 and UseCanonicalName yes in your Apache config.

To avoid that, use a full URL, for example specifying the host name the client used for this request:
Code:
RewriteRule ^.*/index.html$ http://%{HTTP_HOST}/ [R]
If you use the Redirect family of directives, you will need to use an explicit host name, since they do not support the %{..} syntax.

Last edited by Nominal Animal; 07-21-2011 at 01:54 PM. Reason: Found the controlling directives. Fun-ky. Added note about Redirect.
 
1 members found this post helpful.
Old 07-21-2011, 03:56 PM   #3
helptonewbie
Member
 
Registered: Aug 2006
Location: England Somewhere
Distribution: Mandriva, PCLinuxOS, Karoshi, Suse, Redhat, Ubuntu
Posts: 518

Original Poster
Rep: Reputation: 39
Hi Nominal Animal,

Great reply, many thanks. However Apache defaults suggest both UseCanonicalPhysicalPort and UseCanonicalName are Off, and thus Off from what I've read in the documentation is the correct position, that means that Apache should honour the client request Name and port number as such it should be normal. Because the client requests Host www.example.com and not www.example.com:81. Also in the ServerName configs of my VirtalHosts I dont have them set-up as www.example.com:81 anyway, they are set-up as normal ServerName www.example.com and its the Virtual Host directive where I have *:81

For anyone that looks http://httpd.apache.org/docs/current...alphysicalport

But that was a great answer, I was aware I can re-write the rule to include the host and it solves the problem but I really didn't want to have to go changing the mass of places where this situation occurs in our set-up.

Its a loss to me though why apache is honouring the Physical port rather than the client requested port, because the load balancer forwards the request onto 81 instead of 80 is that where its getting lost? I mean the load balancer certainly isn't adding :81 to the Host: header of the request so I dont know how Apache is deciding the port should be :81....

The apache Doc's say this "instead relying on all configured information to construct a valid port number." - but doesn't go on to say what "all configured information" is exactly, so how might I find out what Apache is really looking at here?

Cheers,
M
 
Old 07-21-2011, 10:34 PM   #4
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by helptonewbie View Post
However Apache defaults suggest both UseCanonicalPhysicalPort and UseCanonicalName are Off, and thus Off from what I've read in the documentation is the correct position, that means that Apache should honour the client request Name and port number as such it should be normal.
I checked the Apache sources. For mod_alias, i.e. Redirect* directives, if the final URL starts with a slash, the server name will be prepended to it. If the port named in the request headers differs from the port configured for the virtual host, the configured port number will always be included. There is no configuration option to change that behaviour. If you are interested, look at core.c:ap_construct_url() function; it is called by mod_alias.c:translate_alias_redir().
 
Old 07-22-2011, 05:39 AM   #5
helptonewbie
Member
 
Registered: Aug 2006
Location: England Somewhere
Distribution: Mandriva, PCLinuxOS, Karoshi, Suse, Redhat, Ubuntu
Posts: 518

Original Poster
Rep: Reputation: 39
Wow, That's cool. Not something I'd be able to do.

Doesn't that not slightly contradict the documentation when it comes to CanonicalPorts and Name? Where if set to Off then Apache won't use the physical ports, but the ones requested by the client, and the client is merely requesting http and then the load balancer probably NAT rewrites to forward the request to 81 but

Is this only going to happen for a final URL of / then? Why would it not keep to the same methods if final destination was /dir/file? As to me both methods should end up with the same redirect reply (sort of - certainly when talking of the hostname and port number thats replied with)

I looked at the 'Port' option - sounded like it might solve the problem, but shame its not in version 2.x
Also I wondered if things would work correctly if I forced in this case 'ServerName www.example.com:80' Or you say it pulls the details from VirtualHost settings though.

Cheers,
M
 
Old 07-23-2011, 02:14 PM   #6
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by helptonewbie View Post
Doesn't that not slightly contradict the documentation when it comes to CanonicalPorts and Name?
Correct. The behaviour does not match the documentation.

The patch to modify the behaviour to match the documentation is pretty much trivial, but I for one don't have the energy to start fighting the developers right now. It is a behavioural change, and most likely their preferred response is to simply modify the documentation, not the behaviour. Especially since the workaround is to name the server explicitly, or to use mod_rewrite.

Even if they did accept the patch, it would take at least half a year (maybe a year for RHEL/CentOS/ScientificLinux et al.) to propagate down into Linux distributions.

Quote:
Originally Posted by helptonewbie View Post
Is this only going to happen for a final URL of / then? Why would it not keep to the same methods if final destination was /dir/file?
This happens whenever the target URL for a Redirect , RedirectTemp, or RedirectMatch directive begins with a slash. It does not need to be a slash only.

Like I wrote earlier, the Redirect* directives are provided by the mod_alias module. One simple workaround is to rewrite the redirections using mod_rewrite, i.e.
Code:
RewriteRule pattern http://%{HTTP_HOST}/path [R=301]
because unlike mod_alias, mod_rewrite allows you to use request header values in the target URL. The %{HTTP_HOST} used in the above example is replaced by the host name the client used for the current request.

Quote:
Originally Posted by helptonewbie View Post
Also I wondered if things would work correctly if I forced in this case 'ServerName www.example.com:80' Or you say it pulls the details from VirtualHost settings though.
The source code compares the port specified in the request headers, and the port specified for the VirtualHost. If they differ, the code will put the VirtualHost port into the redirected URL. So, I don't think that ServerName will help.

But, like I said, that only happens when using Redirect* family of directives, with a target URL beginning with a slash. Perhaps the simplest workaround is to just prepend the scheme and host name ( http://your.ser.ver ) to the target URL. Apache will not modify the target URL at all then.

I do realise it is a bit tedious, especially if you have a lot of them, but those seem to be your options for now.
 
1 members found this post helpful.
Old 08-01-2011, 03:11 PM   #7
helptonewbie
Member
 
Registered: Aug 2006
Location: England Somewhere
Distribution: Mandriva, PCLinuxOS, Karoshi, Suse, Redhat, Ubuntu
Posts: 518

Original Poster
Rep: Reputation: 39
Thanks for a great reply yet again @Nominal Animal
Quote:
Like I wrote earlier, the Redirect* directives are provided by the mod_alias module. One simple workaround is to rewrite the redirections using mod_rewrite, i.e.
Not 100% on what you meant here though, the redirects we're doing were already by mod_rewrite, unless there's a part of mod_rewrite that uses mod_alias or something?

We could add things like (http://%{HTTP_HOST}) scheme and hostname but the problem is we then need to double up everything so we can start catching when the request was via https or http to rewrite the correct schema. But as you say all this work as there are a lot... probably is our only sorry option.

Many thanks again though!!!
 
Old 08-02-2011, 02:27 AM   #8
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by helptonewbie View Post
Not 100% on what you meant here though, the redirects we're doing were already by mod_rewrite, unless there's a part of mod_rewrite that uses mod_alias or something?
I assumed you were using mod_alias (Redirect* family of directives) since mod_rewrite (Rewrite* family of directives) does provide useful workarounds.

First, set the proper scheme into an environment variable before any of the RewriteRules are evaluated:
Code:
RewriteEngine On
RewriteCond %{HTTPS} ^on
RewriteRule $ - [E=SCHEME:https,S=1]
RewriteRule $ - [E=SCHEME:http]
If you use an SSL offloader in your load balancer, configure it to set a custom header for requests using SSL/TLS, and change the RewriteCond above to match. (You can check any request header using %{HTTP:header} in the RewriteCond test string.)

Then, modify those RewriteRules that can cause a redirect to something like
Code:
RewriteRule expression %{ENV:SCHEME}://%{HTTP_HOST}/path [R=status]
where /path can of course be just / if you want to redirect to the initial page.

I did test this only lightly, but it seems to work fine for me. Does it fulfill your needs?
 
1 members found this post helpful.
Old 08-02-2011, 10:45 AM   #9
helptonewbie
Member
 
Registered: Aug 2006
Location: England Somewhere
Distribution: Mandriva, PCLinuxOS, Karoshi, Suse, Redhat, Ubuntu
Posts: 518

Original Poster
Rep: Reputation: 39
That sounds awesome and is just the thing for it. I'll give it a go and let you know how it went.
Thanks again for your help!
 
Old 08-27-2011, 05:27 PM   #10
helptonewbie
Member
 
Registered: Aug 2006
Location: England Somewhere
Distribution: Mandriva, PCLinuxOS, Karoshi, Suse, Redhat, Ubuntu
Posts: 518

Original Poster
Rep: Reputation: 39
It works awesome.

Thanks!!
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] apache incorrectly handling requests for numeric php filenames...mod_rewrite problem? sneakyimp Linux - Server 8 11-17-2009 12:30 AM
simple apache mod_rewrite problem (newbie) rtnylw Linux - Server 7 08-08-2009 11:38 AM
Apache mod_rewrite CondRewrite infinite loop problem jika Linux - Server 2 05-01-2007 07:25 AM
problem with apache mod_rewrite nephish Linux - Software 0 01-22-2007 08:57 AM
Apache virtual hosts and mod_rewrite problem Gyper Debian 3 07-31-2006 11:22 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Server

All times are GMT -5. The time now is 09:49 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration